mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-28 20:21:10 -04:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
			dark-date-
			...
			dark-mode
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7b9c7c3528 | |||
| d1ab4a8021 | |||
| 45aaee72d8 | |||
| f4bc78ce98 | |||
| ba769864d4 | |||
| de235a91e5 | |||
| 18dc88682c | |||
| deb039ba02 | |||
| 7e80bfb507 | |||
| 8a5632c7d6 | |||
| 1a4309ca69 | 
| @ -43,6 +43,12 @@ | ||||
|             max-w-full | ||||
|             left-0 | ||||
|             top-3 | ||||
|             bg-white | ||||
|             dark:border | ||||
|             dark:border-white/10 | ||||
|             dark:text-white | ||||
|             dark:bg-gray-800 | ||||
|             dark:shadow-glass | ||||
|           " | ||||
|         > | ||||
|           <div | ||||
| @ -53,7 +59,7 @@ | ||||
|               ring-1 ring-black ring-opacity-5 | ||||
|             " | ||||
|           > | ||||
|             <div class="relative grid bg-white"> | ||||
|             <div class="relative grid bg-white dark:bg-gray-800"> | ||||
|               <div class="relative p-4"> | ||||
|                 <BaseInput | ||||
|                   v-model="textSearch" | ||||
| @ -66,7 +72,7 @@ | ||||
|  | ||||
|               <div | ||||
|                 v-if="filteredNotes.length > 0" | ||||
|                 class="relative flex flex-col overflow-auto list max-h-36" | ||||
|                 class="relative flex flex-col overflow-auto list max-h-36 dark:border-white/10" | ||||
|               > | ||||
|                 <div | ||||
|                   v-for="(note, index) in filteredNotes" | ||||
| @ -79,6 +85,8 @@ | ||||
|                     cursor-pointer | ||||
|                     hover:bg-gray-100 hover:cursor-pointer | ||||
|                     last:border-b-0 | ||||
|                     dark:border-gray-600 | ||||
|                     dark:border-white/10 dark:hover:bg-gray-700/30 | ||||
|                   " | ||||
|                   @click="selectNote(index, close)" | ||||
|                 > | ||||
| @ -119,6 +127,10 @@ | ||||
|                 bg-gray-200 | ||||
|                 border-none | ||||
|                 outline-none | ||||
|                 dark:bg-gray-600/70 | ||||
|                 dark:backdrop-blur-xl | ||||
|                 dark:shadow-glass | ||||
|                 dark:hover:bg-gray-600/80 | ||||
|               " | ||||
|               @click="openNoteModal" | ||||
|             > | ||||
|  | ||||
| @ -1,5 +1,13 @@ | ||||
| <template> | ||||
|   <tr class="box-border bg-white border border-gray-200 border-solid rounded-b"> | ||||
|   <tr | ||||
|     class=" | ||||
|       box-border | ||||
|       bg-white | ||||
|       border border-gray-200 border-solid | ||||
|       rounded-b | ||||
|       dark:shadow-glass dark:border dark:border-white/10 dark:bg-gray-800/70 | ||||
|       " | ||||
|     > | ||||
|     <td colspan="5" class="p-0 text-left align-top"> | ||||
|       <table class="w-full"> | ||||
|         <colgroup> | ||||
| @ -130,7 +138,7 @@ | ||||
|                 <div class="flex items-center justify-center w-6 h-10 mx-2"> | ||||
|                   <BaseIcon | ||||
|                     v-if="showRemoveButton" | ||||
|                     class="h-5 text-gray-700 cursor-pointer" | ||||
|                     class="h-5 dark:text-red-400 cursor-pointer" | ||||
|                     name="TrashIcon" | ||||
|                     @click="store.removeItem(index)" | ||||
|                   /> | ||||
|  | ||||
| @ -30,7 +30,22 @@ | ||||
|         <template v-if="userStore.hasAbilities(ability)" #action> | ||||
|           <button | ||||
|             type="button" | ||||
|             class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none cursor-pointer " | ||||
|             class=" | ||||
|               flex | ||||
|               items-center | ||||
|               justify-center | ||||
|               w-full | ||||
|               px-2 | ||||
|               py-2 | ||||
|               bg-gray-200 | ||||
|               border-none | ||||
|               outline-none | ||||
|               cursor-pointer | ||||
|               dark:bg-gray-600/70 | ||||
|               dark:backdrop-blur-xl | ||||
|               dark:shadow-glass | ||||
|               dark:hover:bg-gray-600/80 | ||||
|             " | ||||
|             @click="openTaxModal" | ||||
|           > | ||||
|             <BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" /> | ||||
| @ -53,7 +68,7 @@ | ||||
|       <BaseIcon | ||||
|         v-if="taxes.length && index !== taxes.length - 1" | ||||
|         name="TrashIcon" | ||||
|         class="h-5 text-gray-700 cursor-pointer" | ||||
|         class="h-5 text-gray-700 dark:text-red-400 cursor-pointer" | ||||
|         @click="removeTax(index)" | ||||
|       /> | ||||
|     </div> | ||||
|  | ||||
| @ -1,155 +1,172 @@ | ||||
| <template> | ||||
|   <table class="text-center item-table min-w-full"> | ||||
|     <colgroup> | ||||
|       <col style="width: 40%; min-width: 280px" /> | ||||
|       <col style="width: 10%; min-width: 120px" /> | ||||
|       <col style="width: 15%; min-width: 120px" /> | ||||
|       <col | ||||
|         v-if="store[storeProp].discount_per_item === 'YES'" | ||||
|         style="width: 15%; min-width: 160px" | ||||
|       /> | ||||
|       <col style="width: 15%; min-width: 120px" /> | ||||
|     </colgroup> | ||||
|     <thead class="bg-white border border-gray-200 border-solid"> | ||||
|       <tr> | ||||
|         <th | ||||
|           class=" | ||||
|             px-5 | ||||
|             py-3 | ||||
|             text-sm | ||||
|             not-italic | ||||
|             font-medium | ||||
|             leading-5 | ||||
|             text-left text-gray-700 | ||||
|             border-t border-b border-gray-200 border-solid | ||||
|           " | ||||
|         > | ||||
|           <BaseContentPlaceholders v-if="isLoading"> | ||||
|             <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|           </BaseContentPlaceholders> | ||||
|           <span v-else class="pl-7"> | ||||
|             {{ $tc('items.item', 2) }} | ||||
|           </span> | ||||
|         </th> | ||||
|         <th | ||||
|           class=" | ||||
|             px-5 | ||||
|             py-3 | ||||
|             text-sm | ||||
|             not-italic | ||||
|             font-medium | ||||
|             leading-5 | ||||
|             text-right text-gray-700 | ||||
|             border-t border-b border-gray-200 border-solid | ||||
|           " | ||||
|         > | ||||
|           <BaseContentPlaceholders v-if="isLoading"> | ||||
|             <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|           </BaseContentPlaceholders> | ||||
|           <span v-else> | ||||
|             {{ $t('invoices.item.quantity') }} | ||||
|           </span> | ||||
|         </th> | ||||
|         <th | ||||
|           class=" | ||||
|             px-5 | ||||
|             py-3 | ||||
|             text-sm | ||||
|             not-italic | ||||
|             font-medium | ||||
|             leading-5 | ||||
|             text-left text-gray-700 | ||||
|             border-t border-b border-gray-200 border-solid | ||||
|           " | ||||
|         > | ||||
|           <BaseContentPlaceholders v-if="isLoading"> | ||||
|             <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|           </BaseContentPlaceholders> | ||||
|           <span v-else> | ||||
|             {{ $t('invoices.item.price') }} | ||||
|           </span> | ||||
|         </th> | ||||
|         <th | ||||
|   <div class="relative" > | ||||
|     <BaseDarkHighlight class="z-[-1]" /> | ||||
|     <table class="text-center item-table min-w-full"> | ||||
|       <colgroup> | ||||
|         <col style="width: 40%; min-width: 280px" /> | ||||
|         <col style="width: 10%; min-width: 120px" /> | ||||
|         <col style="width: 15%; min-width: 120px" /> | ||||
|         <col | ||||
|           v-if="store[storeProp].discount_per_item === 'YES'" | ||||
|           class=" | ||||
|             px-5 | ||||
|             py-3 | ||||
|             text-sm | ||||
|             not-italic | ||||
|             font-medium | ||||
|             leading-5 | ||||
|             text-left text-gray-700 | ||||
|             border-t border-b border-gray-200 border-solid | ||||
|           " | ||||
|         > | ||||
|           <BaseContentPlaceholders v-if="isLoading"> | ||||
|             <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|           </BaseContentPlaceholders> | ||||
|           <span v-else> | ||||
|             {{ $t('invoices.item.discount') }} | ||||
|           </span> | ||||
|         </th> | ||||
|         <th | ||||
|           class=" | ||||
|             px-5 | ||||
|             py-3 | ||||
|             text-sm | ||||
|             not-italic | ||||
|             font-medium | ||||
|             leading-5 | ||||
|             text-right text-gray-700 | ||||
|             border-t border-b border-gray-200 border-solid | ||||
|           " | ||||
|         > | ||||
|           <BaseContentPlaceholders v-if="isLoading"> | ||||
|             <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|           </BaseContentPlaceholders> | ||||
|           <span v-else class="pr-10 column-heading"> | ||||
|             {{ $t('invoices.item.amount') }} | ||||
|           </span> | ||||
|         </th> | ||||
|       </tr> | ||||
|     </thead> | ||||
|     <draggable | ||||
|       v-model="store[storeProp].items" | ||||
|       item-key="id" | ||||
|       tag="tbody" | ||||
|       handle=".handle" | ||||
|     > | ||||
|       <template #item="{ element, index }"> | ||||
|         <Item | ||||
|           :key="element.id" | ||||
|           :index="index" | ||||
|           :item-data="element" | ||||
|           :loading="isLoading" | ||||
|           :currency="defaultCurrency" | ||||
|           :item-validation-scope="itemValidationScope" | ||||
|           :invoice-items="store[storeProp].items" | ||||
|           :store="store" | ||||
|           :store-prop="storeProp" | ||||
|           style="width: 15%; min-width: 160px" | ||||
|         /> | ||||
|       </template> | ||||
|     </draggable> | ||||
|   </table> | ||||
|         <col style="width: 15%; min-width: 120px" /> | ||||
|       </colgroup> | ||||
|       <thead | ||||
|         class=" | ||||
|           bg-white | ||||
|           border | ||||
|           border-gray-200 | ||||
|           border-solid | ||||
|           dark:shadow-glass dark:border dark:border-white/10 dark:bg-gray-800/70 | ||||
|         " | ||||
|       > | ||||
|         <tr> | ||||
|           <th | ||||
|             class=" | ||||
|               px-5 | ||||
|               py-3 | ||||
|               text-sm | ||||
|               not-italic | ||||
|               font-medium | ||||
|               leading-5 | ||||
|               text-left text-gray-700 | ||||
|               border-t border-b border-gray-200 border-solid | ||||
|               dark:text-white dark:border-white/10 | ||||
|             " | ||||
|           > | ||||
|             <BaseContentPlaceholders v-if="isLoading"> | ||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|             </BaseContentPlaceholders> | ||||
|             <span v-else class="pl-7"> | ||||
|               {{ $tc('items.item', 2) }} | ||||
|             </span> | ||||
|           </th> | ||||
|           <th | ||||
|             class=" | ||||
|               px-5 | ||||
|               py-3 | ||||
|               text-sm | ||||
|               not-italic | ||||
|               font-medium | ||||
|               leading-5 | ||||
|               text-right text-gray-700 | ||||
|               border-t border-b border-gray-200 border-solid | ||||
|               dark:text-white dark:border-white/10 | ||||
|             " | ||||
|           > | ||||
|             <BaseContentPlaceholders v-if="isLoading"> | ||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|             </BaseContentPlaceholders> | ||||
|             <span v-else> | ||||
|               {{ $t('invoices.item.quantity') }} | ||||
|             </span> | ||||
|           </th> | ||||
|           <th | ||||
|             class=" | ||||
|               px-5 | ||||
|               py-3 | ||||
|               text-sm | ||||
|               not-italic | ||||
|               font-medium | ||||
|               leading-5 | ||||
|               text-left text-gray-700 | ||||
|               border-t border-b border-gray-200 border-solid | ||||
|               dark:text-white dark:border-white/10 | ||||
|             " | ||||
|           > | ||||
|             <BaseContentPlaceholders v-if="isLoading"> | ||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|             </BaseContentPlaceholders> | ||||
|             <span v-else> | ||||
|               {{ $t('invoices.item.price') }} | ||||
|             </span> | ||||
|           </th> | ||||
|           <th | ||||
|             v-if="store[storeProp].discount_per_item === 'YES'" | ||||
|             class=" | ||||
|               px-5 | ||||
|               py-3 | ||||
|               text-sm | ||||
|               not-italic | ||||
|               font-medium | ||||
|               leading-5 | ||||
|               text-left text-gray-700 | ||||
|               border-t border-b border-gray-200 border-solid | ||||
|               dark:text-white dark:border-white/10 | ||||
|             " | ||||
|           > | ||||
|             <BaseContentPlaceholders v-if="isLoading"> | ||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|             </BaseContentPlaceholders> | ||||
|             <span v-else> | ||||
|               {{ $t('invoices.item.discount') }} | ||||
|             </span> | ||||
|           </th> | ||||
|           <th | ||||
|             class=" | ||||
|               px-5 | ||||
|               py-3 | ||||
|               text-sm | ||||
|               not-italic | ||||
|               font-medium | ||||
|               leading-5 | ||||
|               text-right text-gray-700 | ||||
|               border-t border-b border-gray-200 border-solid | ||||
|               dark:text-white dark:border-white/10 | ||||
|             " | ||||
|           > | ||||
|             <BaseContentPlaceholders v-if="isLoading"> | ||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||
|             </BaseContentPlaceholders> | ||||
|             <span v-else class="pr-10 column-heading"> | ||||
|               {{ $t('invoices.item.amount') }} | ||||
|             </span> | ||||
|           </th> | ||||
|         </tr> | ||||
|       </thead> | ||||
|       <draggable | ||||
|         v-model="store[storeProp].items" | ||||
|         item-key="id" | ||||
|         tag="tbody" | ||||
|         handle=".handle" | ||||
|       > | ||||
|         <template #item="{ element, index }"> | ||||
|           <Item | ||||
|             :key="element.id" | ||||
|             :index="index" | ||||
|             :item-data="element" | ||||
|             :loading="isLoading" | ||||
|             :currency="defaultCurrency" | ||||
|             :item-validation-scope="itemValidationScope" | ||||
|             :invoice-items="store[storeProp].items" | ||||
|             :store="store" | ||||
|             :store-prop="storeProp" | ||||
|           /> | ||||
|         </template> | ||||
|       </draggable> | ||||
|     </table> | ||||
|  | ||||
|   <div | ||||
|     class=" | ||||
|       flex | ||||
|       items-center | ||||
|       justify-center | ||||
|       w-full | ||||
|       px-6 | ||||
|       py-3 | ||||
|       text-base | ||||
|       border border-t-0 border-gray-200 border-solid | ||||
|       cursor-pointer | ||||
|       text-primary-400 | ||||
|       hover:bg-primary-100 | ||||
|     " | ||||
|     @click="store.addItem" | ||||
|   > | ||||
|     <BaseIcon name="PlusCircleIcon" class="mr-2" /> | ||||
|     {{ $t('general.add_new_item') }} | ||||
|     <div | ||||
|       class=" | ||||
|         flex | ||||
|         items-center | ||||
|         justify-center | ||||
|         w-full | ||||
|         px-6 | ||||
|         py-3 | ||||
|         text-base | ||||
|         border border-t-0 border-gray-200 border-solid | ||||
|         cursor-pointer | ||||
|         text-primary-400 | ||||
|         hover:bg-primary-100 | ||||
|         dark:bg-gray-900/50 dark:border-white/10 dark:hover:bg-gray-900/80 | ||||
|       " | ||||
|       @click="store.addItem" | ||||
|     > | ||||
|       <BaseIcon name="PlusCircleIcon" class="mr-2" /> | ||||
|       {{ $t('general.add_new_item') }} | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
|       mt-6 | ||||
|       bg-white | ||||
|       border border-gray-200 border-solid | ||||
|       dark:bg-gray-800/50 dark:border-white/10 | ||||
|       rounded | ||||
|       md:min-w-[390px] | ||||
|       min-w-[300px] | ||||
| @ -192,6 +193,7 @@ | ||||
|         pt-2 | ||||
|         mt-5 | ||||
|         border-t border-gray-200 border-solid | ||||
|         dark:border-gray-600 | ||||
|       " | ||||
|     > | ||||
|       <BaseContentPlaceholders v-if="isLoading"> | ||||
| @ -199,7 +201,7 @@ | ||||
|       </BaseContentPlaceholders> | ||||
|       <label | ||||
|         v-else | ||||
|         class="m-0 text-sm font-semibold leading-5 text-gray-400 uppercase" | ||||
|         class="m-0 text-sm font-semibold leading-5 text-gray-400 uppercase dark:text-gray-400" | ||||
|         >{{ $t('estimates.total') }} {{ $t('estimates.amount') }}:</label | ||||
|       > | ||||
|  | ||||
|  | ||||
| @ -17,7 +17,7 @@ | ||||
|  | ||||
|       <BaseIcon | ||||
|         name="TrashIcon" | ||||
|         class="h-5 ml-2 cursor-pointer" | ||||
|         class="h-5 ml-2 cursor-pointer dark:text-red-400" | ||||
|         @click="$emit('remove', tax.id)" | ||||
|       /> | ||||
|     </label> | ||||
|  | ||||
| @ -44,7 +44,7 @@ | ||||
|             > | ||||
|               <!-- Tax Search Input  --> | ||||
|  | ||||
|               <div class="relative bg-white"> | ||||
|               <div class="relative bg-white dark:bg-gray-800"> | ||||
|                 <div class="relative p-4"> | ||||
|                   <BaseInput | ||||
|                     v-model="textSearch" | ||||
| @ -65,13 +65,14 @@ | ||||
|                     list | ||||
|                     max-h-36 | ||||
|                     border-t border-gray-200 | ||||
|                     dark:border-gray-600 | ||||
|                   " | ||||
|                 > | ||||
|                   <div | ||||
|                     v-for="(taxType, index) in filteredTaxType" | ||||
|                     :key="index" | ||||
|                     :class="{ | ||||
|                       'bg-gray-100 cursor-not-allowed opacity-50 pointer-events-none': | ||||
|                       'bg-gray-100 cursor-not-allowed opacity-50 pointer-events-none dark:bg-gray-900': | ||||
|                         taxes.find((val) => { | ||||
|                           return val.tax_type_id === taxType.id | ||||
|                         }), | ||||
| @ -84,6 +85,7 @@ | ||||
|                       cursor-pointer | ||||
|                       hover:bg-gray-100 hover:cursor-pointer | ||||
|                       last:border-b-0 | ||||
|                       dark:border-gray-600 dark:hover:bg-gray-700/20 | ||||
|                     " | ||||
|                     @click="selectTaxType(taxType, close)" | ||||
|                   > | ||||
| @ -140,6 +142,10 @@ | ||||
|                   bg-gray-200 | ||||
|                   border-none | ||||
|                   outline-none | ||||
|                   dark:bg-gray-600/70 | ||||
|                   dark:backdrop-blur-xl | ||||
|                   dark:shadow-glass | ||||
|                   dark:hover:bg-gray-600/80 | ||||
|                 " | ||||
|                 @click="openTaxTypeModal" | ||||
|               > | ||||
|  | ||||
| @ -40,6 +40,7 @@ | ||||
|             px-4 | ||||
|             md:px-8 | ||||
|             py-1.5 | ||||
|             dark:text-gray-200 | ||||
|           " | ||||
|         > | ||||
|           {{ $tc('settings.roles.permission', 2) }} | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| <template> | ||||
|   <div class="h-screen overflow-y-auto text-base"> | ||||
|   <div class="h-screen overflow-y-auto text-base dark:bg-gray-800/80 dark:text-white"> | ||||
|     <NotificationRoot /> | ||||
|  | ||||
|     <div class="container mx-auto px-4"> | ||||
|     <div class="container px-4 mx-auto"> | ||||
|       <router-view /> | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <div class="grid h-screen grid-cols-12 overflow-y-hidden bg-gray-100"> | ||||
|   <div class="grid h-screen grid-cols-12 overflow-y-hidden bg-gray-100 dark:bg-gray-900"> | ||||
|     <NotificationRoot /> | ||||
|  | ||||
|     <div | ||||
|  | ||||
| @ -68,10 +68,8 @@ | ||||
|           </TransitionChild> | ||||
|           <div class="flex-1 h-0 pt-5 pb-4 overflow-y-auto"> | ||||
|             <div class="flex items-center shrink-0 px-4 mb-10"> | ||||
|               <MainLogo | ||||
|                 class="block h-auto max-w-full w-36 text-primary-400" | ||||
|                 alt="Crater Logo" | ||||
|               /> | ||||
|               <img class="h-auto max-w-full w-36 hidden dark:block" :src="getDarkLogo"/> | ||||
|               <img class="h-auto max-w-full w-36 block dark:hidden" :src="getLightLogo"/> | ||||
|             </div> | ||||
|  | ||||
|             <nav | ||||
| @ -95,7 +93,7 @@ | ||||
|                   :name="item.icon" | ||||
|                   :class="[ | ||||
|                     hasActiveUrl(item.link) | ||||
|                       ? 'text-primary-500 ' | ||||
|                       ? 'text-primary-500 dark:text-primary-400' | ||||
|                       : 'text-gray-400', | ||||
|                     'mr-4 shrink-0 h-5 w-5', | ||||
|                   ]" | ||||
| @ -151,7 +149,7 @@ | ||||
|           :name="item.icon" | ||||
|           :class="[ | ||||
|             hasActiveUrl(item.link) | ||||
|               ? 'text-primary-500 group-hover:text-primary-500 dark:text-primary-400 dark:group-hover:text-primary-500 ' | ||||
|               ? 'text-primary-500 dark:text-primary-400' | ||||
|               : 'text-gray-400 group-hover:text-black dark:text-gray-400 dark:group-hover:text-white', | ||||
|             'mr-4 shrink-0 h-5 w-5 ', | ||||
|           ]" | ||||
| @ -167,8 +165,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import MainLogo from '@/scripts/components/icons/MainLogo.vue' | ||||
|  | ||||
| import { computed } from 'vue' | ||||
| import { | ||||
|   Dialog, | ||||
|   DialogOverlay, | ||||
| @ -183,6 +180,9 @@ import LightDarkSwitch from '@/scripts/components/LightDarkSwitcher.vue' | ||||
| const route = useRoute() | ||||
| const globalStore = useGlobalStore() | ||||
|  | ||||
| const getDarkLogo = computed(() => new URL('/img/logo-white.png', import.meta.url)) | ||||
| const getLightLogo = computed(() => new URL('/img/crater-logo.png', import.meta.url)) | ||||
|  | ||||
| function hasActiveUrl(url) { | ||||
|   return route.path.indexOf(url) > -1 | ||||
| } | ||||
|  | ||||
| @ -34,8 +34,7 @@ export const useGlobalStore = (useWindow = false) => { | ||||
|       isAppLoaded: false, | ||||
|       isSidebarOpen: false, | ||||
|       areCurrenciesLoading: false, | ||||
|       isDarkModeOn: false, | ||||
|  | ||||
|       isDarkModeOn: localStorage.getItem('theme') === 'dark' || document.documentElement.classList.contains('dark'), | ||||
|       downloadReport: null, | ||||
|     }), | ||||
|  | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
|     <div class="mt-4 mb-4 text-sm"> | ||||
|       <router-link | ||||
|         to="/login" | ||||
|         class="text-sm text-primary-400 hover:text-gray-700" | ||||
|         class="text-sm text-primary-400 hover:text-gray-700 dark:hover:text-primary-500" | ||||
|       > | ||||
|         {{ $t('general.back_to_login') }} | ||||
|       </router-link> | ||||
|  | ||||
| @ -49,7 +49,7 @@ | ||||
|       <div class="mb-4"> | ||||
|         <router-link | ||||
|           to="forgot-password" | ||||
|           class="text-sm text-primary-400 hover:text-gray-700" | ||||
|           class="text-sm text-primary-400 hover:text-gray-700 dark:hover:text-primary-500" | ||||
|         > | ||||
|           {{ $t('login.forgot_password') }} | ||||
|         </router-link> | ||||
|  | ||||
| @ -113,7 +113,7 @@ | ||||
|             </span> | ||||
|           </template> | ||||
|           <BaseDropdownItem @click="removeMultipleCustomers"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -154,7 +154,7 @@ | ||||
|               :text="row.data.name" | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="font-medium text-primary-500 flex flex-col" | ||||
|               class="font-medium text-primary-500 flex flex-col dark:text-primary-400" | ||||
|             /> | ||||
|             <BaseText | ||||
|               :text="row.data.contact_name ? row.data.contact_name : ''" | ||||
|  | ||||
| @ -34,8 +34,8 @@ | ||||
|             v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)" | ||||
|             :to="`/admin/estimates/create?customer=${$route.params.id}`" | ||||
|           > | ||||
|             <BaseDropdownItem class=""> | ||||
|               <BaseIcon name="DocumentIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseDropdownItem v-slot="slotProps"> | ||||
|               <BaseIcon name="DocumentIcon" :class="slotProps.class" /> | ||||
|               {{ $t('estimates.new_estimate') }} | ||||
|             </BaseDropdownItem> | ||||
|           </router-link> | ||||
| @ -44,8 +44,8 @@ | ||||
|             v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)" | ||||
|             :to="`/admin/invoices/create?customer=${$route.params.id}`" | ||||
|           > | ||||
|             <BaseDropdownItem> | ||||
|               <BaseIcon name="DocumentTextIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseDropdownItem v-slot="slotProps"> | ||||
|               <BaseIcon name="DocumentTextIcon" :class="slotProps.class" /> | ||||
|               {{ $t('invoices.new_invoice') }} | ||||
|             </BaseDropdownItem> | ||||
|           </router-link> | ||||
| @ -54,8 +54,8 @@ | ||||
|             v-if="userStore.hasAbilities(abilities.CREATE_PAYMENT)" | ||||
|             :to="`/admin/payments/create?customer=${$route.params.id}`" | ||||
|           > | ||||
|             <BaseDropdownItem> | ||||
|               <BaseIcon name="CreditCardIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseDropdownItem v-slot="slotProps"> | ||||
|               <BaseIcon name="CreditCardIcon" :class="slotProps.class" /> | ||||
|               {{ $t('payments.new_payment') }} | ||||
|             </BaseDropdownItem> | ||||
|           </router-link> | ||||
| @ -64,8 +64,8 @@ | ||||
|             v-if="userStore.hasAbilities(abilities.CREATE_EXPENSE)" | ||||
|             :to="`/admin/expenses/create?customer=${$route.params.id}`" | ||||
|           > | ||||
|             <BaseDropdownItem> | ||||
|               <BaseIcon name="CalculatorIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseDropdownItem v-slot="slotProps"> | ||||
|               <BaseIcon name="CalculatorIcon" :class="slotProps.class" /> | ||||
|               {{ $t('expenses.new_expense') }} | ||||
|             </BaseDropdownItem> | ||||
|           </router-link> | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
|       xl:ml-64 | ||||
|       w-88 | ||||
|       xl:block | ||||
|       dark:bg-gray-800 | ||||
|     " | ||||
|   > | ||||
|     <div | ||||
| @ -25,6 +26,7 @@ | ||||
|         pb-2 | ||||
|         border border-gray-200 border-solid | ||||
|         height-full | ||||
|         dark:border-gray-600 | ||||
|       " | ||||
|     > | ||||
|       <BaseInput | ||||
| @ -59,6 +61,7 @@ | ||||
|               mb-2 | ||||
|               text-sm | ||||
|               border-b border-gray-200 border-solid | ||||
|               dark:border-gray-600 | ||||
|             " | ||||
|           > | ||||
|             {{ $t('general.sort_by') }} | ||||
| @ -114,6 +117,7 @@ | ||||
|         border-l border-gray-200 border-solid | ||||
|         sidebar | ||||
|         base-scroll | ||||
|         dark:border-gray-600 | ||||
|       " | ||||
|     > | ||||
|       <div v-for="(customer, index) in customerList" :key="index"> | ||||
| @ -122,9 +126,9 @@ | ||||
|           :id="'customer-' + customer.id" | ||||
|           :to="`/admin/customers/${customer.id}/view`" | ||||
|           :class="[ | ||||
|             'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent', | ||||
|             'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent dark:hover:bg-gray-700', | ||||
|             { | ||||
|               'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||
|               'bg-gray-100 border-l-4 border-primary-500 border-solid dark:border-primary-400 dark:bg-gray-700': | ||||
|                 hasActiveUrl(customer.id), | ||||
|             }, | ||||
|           ]" | ||||
| @ -143,6 +147,7 @@ | ||||
|                 text-black | ||||
|                 capitalize | ||||
|                 truncate | ||||
|                 dark:text-white | ||||
|               " | ||||
|             /> | ||||
|  | ||||
| @ -157,6 +162,7 @@ | ||||
|                 font-medium | ||||
|                 leading-5 | ||||
|                 text-gray-600 | ||||
|                 dark:text-gray-400 | ||||
|               " | ||||
|             /> | ||||
|           </div> | ||||
| @ -175,7 +181,7 @@ | ||||
|       </div> | ||||
|       <p | ||||
|         v-if="!customerList?.length && !isFetching" | ||||
|         class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||
|         class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" | ||||
|       > | ||||
|         {{ $t('customers.no_matching_customers') }} | ||||
|       </p> | ||||
|  | ||||
| @ -28,7 +28,7 @@ | ||||
|           <template #cell-user="{ row }"> | ||||
|             <router-link | ||||
|               :to="{ path: `invoices/${row.data.id}/view` }" | ||||
|               class="font-medium text-primary-500" | ||||
|               class="font-medium text-primary-500 dark:text-primary-400" | ||||
|             > | ||||
|               {{ row.data.customer.name }} | ||||
|             </router-link> | ||||
| @ -78,7 +78,7 @@ | ||||
|           <template #cell-user="{ row }"> | ||||
|             <router-link | ||||
|               :to="{ path: `estimates/${row.data.id}/view` }" | ||||
|               class="font-medium text-primary-500" | ||||
|               class="font-medium text-primary-500 dark:text-primary-400" | ||||
|             > | ||||
|               {{ row.data.customer.name }} | ||||
|             </router-link> | ||||
|  | ||||
| @ -164,7 +164,7 @@ | ||||
|           </template> | ||||
|  | ||||
|           <BaseDropdownItem @click="removeMultipleEstimates"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -205,7 +205,7 @@ | ||||
|         <template #cell-estimate_number="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `estimates/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.estimate_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -50,6 +50,7 @@ | ||||
|         xl:ml-64 | ||||
|         w-88 | ||||
|         xl:block | ||||
|         dark:bg-gray-800 | ||||
|       " | ||||
|     > | ||||
|       <div | ||||
| @ -62,6 +63,7 @@ | ||||
|           pb-2 | ||||
|           border border-gray-200 border-solid | ||||
|           height-full | ||||
|           dark:border-gray-600 | ||||
|         " | ||||
|       > | ||||
|         <div class="mb-6"> | ||||
| @ -96,9 +98,10 @@ | ||||
|                 px-4 | ||||
|                 py-1 | ||||
|                 pb-2 | ||||
|                 mb-1 mb-2 | ||||
|                 mb-2 | ||||
|                 text-sm | ||||
|                 border-b border-gray-200 border-solid | ||||
|                 dark:border-gray-600 | ||||
|               " | ||||
|             > | ||||
|               {{ $t('general.sort_by') }} | ||||
| @ -161,6 +164,7 @@ | ||||
|           overflow-y-scroll | ||||
|           border-l border-gray-200 border-solid | ||||
|           base-scroll | ||||
|           dark:border-gray-600 | ||||
|         " | ||||
|       > | ||||
|         <div v-for="(estimate, index) in estimateList" :key="index"> | ||||
| @ -169,9 +173,9 @@ | ||||
|             :id="'estimate-' + estimate.id" | ||||
|             :to="`/admin/estimates/${estimate.id}/view`" | ||||
|             :class="[ | ||||
|               'flex justify-between side-estimate p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent', | ||||
|               'flex justify-between side-estimate p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent dark:hover:bg-gray-700', | ||||
|               { | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid dark:border-primary-400 dark:bg-gray-700': | ||||
|                   hasActiveUrl(estimate.id), | ||||
|               }, | ||||
|             ]" | ||||
| @ -191,6 +195,7 @@ | ||||
|                   text-black | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                   dark:text-white | ||||
|                 " | ||||
|               /> | ||||
|  | ||||
| @ -203,6 +208,7 @@ | ||||
|                   font-medium | ||||
|                   leading-5 | ||||
|                   text-gray-600 | ||||
|                   dark:text-gray-400 | ||||
|                 " | ||||
|               > | ||||
|                 {{ estimate.estimate_number }} | ||||
| @ -228,6 +234,7 @@ | ||||
|                   font-semibold | ||||
|                   leading-8 | ||||
|                   text-right text-gray-900 | ||||
|                   dark:text-white | ||||
|                 " | ||||
|               /> | ||||
|  | ||||
| @ -239,6 +246,7 @@ | ||||
|                   leading-5 | ||||
|                   text-right text-gray-600 | ||||
|                   est-date | ||||
|                   dark:text-gray-400 | ||||
|                 " | ||||
|               > | ||||
|                 {{ estimate.formatted_estimate_date }} | ||||
| @ -251,7 +259,7 @@ | ||||
|         </div> | ||||
|         <p | ||||
|           v-if="!estimateList?.length && !isLoading" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" | ||||
|         > | ||||
|           {{ $t('estimates.no_matching_estimates') }} | ||||
|         </p> | ||||
|  | ||||
| @ -135,7 +135,7 @@ | ||||
|             v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)" | ||||
|             @click="removeMultipleExpenses" | ||||
|           > | ||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -171,7 +171,7 @@ | ||||
|         <template #cell-name="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `expenses/${row.data.id}/edit` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.expense_category.name }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <template> | ||||
|   <div class="flex flex-col items-center justify-between w-full pt-10"> | ||||
|     <LightDarkButton class="absolute z-10 top-2 right-2"/> | ||||
|     <img | ||||
|       id="logo-crater" | ||||
|       src="/img/crater-logo.png" | ||||
| @ -29,6 +30,7 @@ import Step7CompanyInfo from './Step7CompanyInfo.vue' | ||||
| import Step8CompanyPreferences from './Step8CompanyPreferences.vue' | ||||
| import { useInstallationStore } from '@/scripts/admin/stores/installation' | ||||
| import { useRouter } from 'vue-router' | ||||
| import LightDarkButton from '@/scripts/components/LightDarkButton.vue' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @ -40,6 +42,7 @@ export default { | ||||
|     step_6: Step6AccountSettings, | ||||
|     step_7: Step7CompanyInfo, | ||||
|     step_8: Step8CompanyPreferences, | ||||
|     LightDarkButton | ||||
|   }, | ||||
|  | ||||
|   setup() { | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|       <div class="mb-6"> | ||||
|         <div | ||||
|           v-if="phpSupportInfo" | ||||
|           class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200  lg:gap-24 sm:gap-4" | ||||
|           class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 lg:gap-24 sm:gap-4 dark:border-white/10" | ||||
|         > | ||||
|           <div class="col-span-2 text-sm"> | ||||
|             {{ | ||||
| @ -32,7 +32,7 @@ | ||||
|           <div | ||||
|             v-for="(requirement, index) in requirements" | ||||
|             :key="index" | ||||
|             class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200  lg:gap-24 sm:gap-4" | ||||
|             class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 dark:border-gray-600 lg:gap-24 sm:gap-4" | ||||
|           > | ||||
|             <div class="col-span-2 text-sm"> | ||||
|               {{ index }} | ||||
|  | ||||
| @ -8,12 +8,7 @@ | ||||
|       <div | ||||
|         v-for="(permission, index) in 3" | ||||
|         :key="index" | ||||
|         class=" | ||||
|           grid grid-flow-row grid-cols-3 | ||||
|           lg:gap-24 | ||||
|           sm:gap-4 | ||||
|           border border-gray-200 | ||||
|         " | ||||
|         class="grid grid-flow-row grid-cols-3 border border-gray-200 lg:gap-24 sm:gap-4 dark:border-gray-600" | ||||
|       > | ||||
|         <BaseContentPlaceholdersText :lines="1" class="col-span-4 p-3" /> | ||||
|       </div> | ||||
| @ -29,7 +24,7 @@ | ||||
|       <div | ||||
|         v-for="(permission, index) in permissions" | ||||
|         :key="index" | ||||
|         class="border border-gray-200" | ||||
|         class="border border-gray-200 dark:border-gray-600" | ||||
|       > | ||||
|         <div class="grid grid-flow-row grid-cols-3 lg:gap-24 sm:gap-4"> | ||||
|           <div class="col-span-2 p-3"> | ||||
| @ -38,11 +33,11 @@ | ||||
|           <div class="p-3 text-right"> | ||||
|             <span | ||||
|               v-if="permission.isSet" | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-green-500" | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 bg-green-500 rounded-full" | ||||
|             /> | ||||
|             <span | ||||
|               v-else | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-red-500" | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 bg-red-500 rounded-full" | ||||
|             /> | ||||
|             <span>{{ permission.permission }}</span> | ||||
|           </div> | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
|   <BaseWizardStep | ||||
|     :title="$t('wizard.database.database')" | ||||
|     :description="$t('wizard.database.desc')" | ||||
|     step-container="w-full p-8 mb-8 bg-white border border-gray-200 border-solid rounded md:w-full" | ||||
|   > | ||||
|     <component | ||||
|       :is="databaseData.database_connection" | ||||
|  | ||||
| @ -18,18 +18,18 @@ | ||||
|       </BaseInputGroup> | ||||
|     </div> | ||||
|  | ||||
|     <p class="mt-4 mb-0 text-sm text-gray-600">Notes:</p> | ||||
|     <ul class="w-full text-gray-600 list-disc list-inside"> | ||||
|     <p class="mt-4 mb-0 text-sm text-gray-600 dark:text-white">Notes:</p> | ||||
|     <ul class="w-full text-gray-600 list-disc list-inside dark:text-gray-300"> | ||||
|       <li class="text-sm leading-8"> | ||||
|         App domain should not contain | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> or | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> in front of | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-md dark:bg-gray-400 dark:text-gray-600">https://</b> or | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-md dark:bg-gray-400 dark:text-gray-600">http</b> in front of | ||||
|         the domain. | ||||
|       </li> | ||||
|       <li class="text-sm leading-8"> | ||||
|         If you're accessing the website on a different port, please mention the | ||||
|         port. For example: | ||||
|         <b class="inline-block px-1 bg-gray-100">localhost:8080</b> | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-md dark:bg-gray-400 dark:text-gray-600">localhost:8080</b> | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
| @ -68,13 +68,15 @@ | ||||
|             @input="v$.userForm.password.$touch()" | ||||
|           > | ||||
|             <template #right> | ||||
|               <EyeOffIcon | ||||
|               <BaseIcon | ||||
|                 v-if="isShowPassword" | ||||
|                 name="EyeOffIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowPassword = !isShowPassword" | ||||
|               /> | ||||
|               <EyeIcon | ||||
|               <BaseIcon | ||||
|                 v-else | ||||
|                 name="EyeIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowPassword = !isShowPassword" | ||||
|               /> | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
|   <BaseWizardStep | ||||
|     :title="$t('wizard.company_info')" | ||||
|     :description="$t('wizard.company_info_desc')" | ||||
|     step-container="bg-white border border-gray-200 border-solid mb-8 md:w-full p-8 rounded w-full" | ||||
|   > | ||||
|     <form action="" @submit.prevent="next"> | ||||
|       <div class="grid grid-cols-1 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
|   <BaseWizardStep | ||||
|     :title="$t('wizard.preferences')" | ||||
|     :description="$t('wizard.preferences_desc')" | ||||
|     step-container="bg-white border border-gray-200 border-solid mb-8 md:w-full p-8 rounded w-full" | ||||
|   > | ||||
|     <form action="" @submit.prevent="next"> | ||||
|       <div> | ||||
|  | ||||
| @ -178,7 +178,7 @@ | ||||
|           </template> | ||||
|  | ||||
|           <BaseDropdownItem @click="removeMultipleInvoices"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -220,7 +220,7 @@ | ||||
|         <template #cell-invoice_number="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `invoices/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.invoice_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -299,6 +299,7 @@ onSearched = debounce(onSearched, 500) | ||||
|         xl:ml-64 | ||||
|         w-88 | ||||
|         xl:block | ||||
|         dark:bg-gray-800 | ||||
|       " | ||||
|     > | ||||
|       <div | ||||
| @ -311,6 +312,7 @@ onSearched = debounce(onSearched, 500) | ||||
|           pb-2 | ||||
|           border border-gray-200 border-solid | ||||
|           height-full | ||||
|           dark:border-gray-600 | ||||
|         " | ||||
|       > | ||||
|         <div class="mb-6"> | ||||
| @ -339,9 +341,10 @@ onSearched = debounce(onSearched, 500) | ||||
|                 px-2 | ||||
|                 py-1 | ||||
|                 pb-2 | ||||
|                 mb-1 mb-2 | ||||
|                 mb-2 | ||||
|                 text-sm | ||||
|                 border-b border-gray-200 border-solid | ||||
|                 dark:border-gray-600 | ||||
|               " | ||||
|             > | ||||
|               {{ $t('general.sort_by') }} | ||||
| @ -404,6 +407,7 @@ onSearched = debounce(onSearched, 500) | ||||
|           overflow-y-scroll | ||||
|           border-l border-gray-200 border-solid | ||||
|           base-scroll | ||||
|           dark:border-gray-600 | ||||
|         " | ||||
|       > | ||||
|         <div v-for="(invoice, index) in invoiceList" :key="index"> | ||||
| @ -412,9 +416,9 @@ onSearched = debounce(onSearched, 500) | ||||
|             :id="'invoice-' + invoice.id" | ||||
|             :to="`/admin/invoices/${invoice.id}/view`" | ||||
|             :class="[ | ||||
|               'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent', | ||||
|               'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent dark:hover:bg-gray-700', | ||||
|               { | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid dark:bg-gray-700': | ||||
|                   hasActiveUrl(invoice.id), | ||||
|               }, | ||||
|             ]" | ||||
| @ -434,6 +438,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                   text-black | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                   dark:text-white | ||||
|                 " | ||||
|               /> | ||||
|  | ||||
| @ -446,16 +451,17 @@ onSearched = debounce(onSearched, 500) | ||||
|                   font-medium | ||||
|                   leading-5 | ||||
|                   text-gray-600 | ||||
|                   dark:text-gray-400 | ||||
|                 " | ||||
|               > | ||||
|                 {{ invoice.invoice_number }} | ||||
|               </div> | ||||
|               <BaseEstimateStatusBadge | ||||
|               <BaseInvoiceStatusBadge | ||||
|                 :status="invoice.status" | ||||
|                 class="px-1 text-xs" | ||||
|               > | ||||
|                 {{ invoice.status }} | ||||
|               </BaseEstimateStatusBadge> | ||||
|               </BaseInvoiceStatusBadge> | ||||
|             </div> | ||||
|  | ||||
|             <div class="flex-1 whitespace-nowrap right"> | ||||
| @ -468,6 +474,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                   leading-8 | ||||
|                   text-right text-gray-900 | ||||
|                   block | ||||
|                   dark:text-white | ||||
|                 " | ||||
|                 :amount="invoice.total" | ||||
|                 :currency="invoice.customer.currency" | ||||
| @ -480,6 +487,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                   leading-5 | ||||
|                   text-right text-gray-600 | ||||
|                   est-date | ||||
|                   dark:text-gray-400 | ||||
|                 " | ||||
|               > | ||||
|                 {{ invoice.formatted_invoice_date }} | ||||
| @ -492,7 +500,7 @@ onSearched = debounce(onSearched, 500) | ||||
|         </div> | ||||
|         <p | ||||
|           v-if="!invoiceList?.length && !isLoading" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" | ||||
|         > | ||||
|           {{ $t('invoices.no_matching_invoices') }} | ||||
|         </p> | ||||
|  | ||||
| @ -117,7 +117,7 @@ | ||||
|             </span> | ||||
|           </template> | ||||
|           <BaseDropdownItem @click="removeMultipleItems"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -153,7 +153,7 @@ | ||||
|         <template #cell-name="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `items/${row.data.id}/edit` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.name }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -116,7 +116,7 @@ | ||||
|             </span> | ||||
|           </template> | ||||
|           <BaseDropdownItem @click="removeMultiplePayments"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -158,7 +158,7 @@ | ||||
|         <template #cell-payment_number="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `payments/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.payment_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -35,6 +35,7 @@ | ||||
|         xl:ml-64 | ||||
|         w-88 | ||||
|         xl:block | ||||
|         dark:bg-gray-800 | ||||
|       " | ||||
|     > | ||||
|       <div | ||||
| @ -46,6 +47,7 @@ | ||||
|           pt-8 | ||||
|           pb-6 | ||||
|           border border-gray-200 border-solid | ||||
|           dark:border-gray-600 | ||||
|         " | ||||
|       > | ||||
|         <BaseInput | ||||
| @ -77,6 +79,7 @@ | ||||
|                 mb-2 | ||||
|                 text-sm | ||||
|                 border-b border-gray-200 border-solid | ||||
|                 dark:border-gray-600 | ||||
|               " | ||||
|             > | ||||
|               {{ $t('general.sort_by') }} | ||||
| @ -139,7 +142,7 @@ | ||||
|  | ||||
|       <div | ||||
|         ref="paymentListSection" | ||||
|         class="h-full overflow-y-scroll border-l border-gray-200 border-solid" | ||||
|         class="h-full overflow-y-scroll border-l border-gray-200 border-solid dark:border-gray-600" | ||||
|       > | ||||
|         <div v-for="(payment, index) in paymentList" :key="index"> | ||||
|           <router-link | ||||
| @ -147,9 +150,9 @@ | ||||
|             :id="'payment-' + payment.id" | ||||
|             :to="`/admin/payments/${payment.id}/view`" | ||||
|             :class="[ | ||||
|               'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent', | ||||
|               'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent dark:hover:bg-gray-700', | ||||
|               { | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||
|                 'bg-gray-100 border-l-4 border-primary-500 border-solid dark:bg-gray-700': | ||||
|                   hasActiveUrl(payment.id), | ||||
|               }, | ||||
|             ]" | ||||
| @ -169,6 +172,7 @@ | ||||
|                   text-black | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                   dark:text-white | ||||
|                 " | ||||
|               /> | ||||
|  | ||||
| @ -181,6 +185,7 @@ | ||||
|                   leading-5 | ||||
|                   text-gray-500 | ||||
|                   capitalize | ||||
|                   dark:text-gray-400 | ||||
|                 " | ||||
|               > | ||||
|                 {{ payment?.payment_number }} | ||||
| @ -211,12 +216,13 @@ | ||||
|                   font-semibold | ||||
|                   leading-8 | ||||
|                   text-right text-gray-900 | ||||
|                   dark:text-white | ||||
|                 " | ||||
|                 :amount="payment?.amount" | ||||
|                 :currency="payment.customer?.currency" | ||||
|               /> | ||||
|  | ||||
|               <div class="text-sm text-right text-gray-500 non-italic"> | ||||
|               <div class="text-sm text-right text-gray-500 non-italic dark:text-gray-400"> | ||||
|                 {{ payment.formatted_payment_date }} | ||||
|               </div> | ||||
|             </div> | ||||
| @ -227,7 +233,7 @@ | ||||
|         </div> | ||||
|         <p | ||||
|           v-if="!paymentList?.length && !isLoading" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||
|           class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" | ||||
|         > | ||||
|           {{ $t('payments.no_matching_payments') }} | ||||
|         </p> | ||||
|  | ||||
| @ -151,12 +151,12 @@ | ||||
|               " | ||||
|             > | ||||
|               {{ $t('general.actions') }} | ||||
|               <BaseIcon name="ChevronDownIcon" class="h-5" /> | ||||
|               <BaseIcon name="ChevronDownIcon"/> | ||||
|             </span> | ||||
|           </template> | ||||
|  | ||||
|           <BaseDropdownItem @click="removeMultipleRecurringInvoices()"> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -204,7 +204,7 @@ | ||||
|               :text="row.data.customer.name" | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="font-medium text-primary-500 flex flex-col" | ||||
|               class="font-medium text-primary-500 flex flex-col dark:text-primary-400" | ||||
|             /> | ||||
|  | ||||
|             <BaseText | ||||
|  | ||||
| @ -152,6 +152,7 @@ onSearched = debounce(onSearched, 500) | ||||
|       xl:ml-64 | ||||
|       w-88 | ||||
|       xl:block | ||||
|       dark:bg-gray-800 | ||||
|     " | ||||
|   > | ||||
|     <div | ||||
| @ -164,6 +165,7 @@ onSearched = debounce(onSearched, 500) | ||||
|         pb-2 | ||||
|         border border-gray-200 border-solid | ||||
|         height-full | ||||
|         dark:border-gray-600 | ||||
|       " | ||||
|     > | ||||
|       <div class="mb-6"> | ||||
| @ -192,9 +194,10 @@ onSearched = debounce(onSearched, 500) | ||||
|               px-2 | ||||
|               py-1 | ||||
|               pb-2 | ||||
|               mb-1 mb-2 | ||||
|               mb-2 | ||||
|               text-sm | ||||
|               border-b border-gray-200 border-solid | ||||
|               dark:border-gray-600 | ||||
|             " | ||||
|           > | ||||
|             {{ $t('general.sort_by') }} | ||||
| @ -243,6 +246,7 @@ onSearched = debounce(onSearched, 500) | ||||
|         overflow-y-scroll | ||||
|         border-l border-gray-200 border-solid | ||||
|         base-scroll | ||||
|         dark:border-gray-600 | ||||
|       " | ||||
|     > | ||||
|       <div v-for="(invoice, index) in invoiceList" :key="index"> | ||||
| @ -251,9 +255,9 @@ onSearched = debounce(onSearched, 500) | ||||
|           :id="'recurring-invoice-' + invoice.id" | ||||
|           :to="`/admin/recurring-invoices/${invoice.id}/view`" | ||||
|           :class="[ | ||||
|             'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent', | ||||
|             'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent dark:hover:bg-gray-700', | ||||
|             { | ||||
|               'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||
|               'bg-gray-100 border-l-4 border-primary-500 border-solid dark:bg-gray-700': | ||||
|                 hasActiveUrl(invoice.id), | ||||
|             }, | ||||
|           ]" | ||||
| @ -273,6 +277,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                 text-black | ||||
|                 capitalize | ||||
|                 truncate | ||||
|                 dark:text-white | ||||
|               " | ||||
|             /> | ||||
|  | ||||
| @ -285,6 +290,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                 font-medium | ||||
|                 leading-5 | ||||
|                 text-gray-600 | ||||
|                 dark:text-gray-400 | ||||
|               " | ||||
|             > | ||||
|               {{ invoice.invoice_number }} | ||||
| @ -307,6 +313,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                 font-semibold | ||||
|                 leading-8 | ||||
|                 text-right text-gray-900 | ||||
|                 dark:text-white | ||||
|               " | ||||
|               :amount="invoice.total" | ||||
|               :currency="invoice.customer.currency" | ||||
| @ -320,6 +327,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                 leading-5 | ||||
|                 text-right text-gray-600 | ||||
|                 est-date | ||||
|                 dark:text-gray-400 | ||||
|               " | ||||
|             > | ||||
|               {{ invoice.formatted_starts_at }} | ||||
| @ -332,7 +340,7 @@ onSearched = debounce(onSearched, 500) | ||||
|       </div> | ||||
|       <p | ||||
|         v-if="!invoiceList?.length && !isLoading" | ||||
|         class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||
|         class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" | ||||
|       > | ||||
|         {{ $t('invoices.no_matching_invoices') }} | ||||
|       </p> | ||||
|  | ||||
| @ -92,7 +92,7 @@ | ||||
|           <tr | ||||
|             v-for="(ext, i) in requiredExtentions" | ||||
|             :key="i" | ||||
|             class="p-2 border-2 border-gray-200" | ||||
|             class="p-2 border-2 border-gray-200 dark:border-gray-600" | ||||
|           > | ||||
|             <td width="70%" class="p-2 text-sm truncate"> | ||||
|               {{ i }} | ||||
| @ -121,7 +121,7 @@ | ||||
|             {{ $t('settings.update_app.update_progress') }} | ||||
|           </h6> | ||||
|           <p | ||||
|             class="mb-8 text-sm leading-snug text-gray-500" | ||||
|             class="mb-8 text-sm leading-snug text-gray-500 dark:text-gray-400" | ||||
|             style="max-width: 480px" | ||||
|           > | ||||
|             {{ $t('settings.update_app.progress_text') }} | ||||
| @ -135,11 +135,11 @@ | ||||
|         <li | ||||
|           v-for="step in updateSteps" | ||||
|           :key="step.stepUrl" | ||||
|           class="flex justify-between w-full py-3 border-b border-gray-200 border-solid last:border-b-0" | ||||
|           class="flex justify-between w-full py-3 border-b border-gray-200 dark:border-gray-600 border-solid last:border-b-0" | ||||
|         > | ||||
|           <p class="m-0 text-sm leading-8">{{ $t(step.translationKey) }}</p> | ||||
|           <p class="m-0 text-sm dark:text-gray-300 leading-8">{{ $t(step.translationKey) }}</p> | ||||
|           <div class="flex flex-row items-center"> | ||||
|             <span v-if="step.time" class="mr-3 text-xs text-gray-500"> | ||||
|             <span v-if="step.time" class="mr-3 text-xs text-gray-500 dark:text-gray-300"> | ||||
|               {{ step.time }} | ||||
|             </span> | ||||
|             <span | ||||
| @ -275,7 +275,7 @@ function statusClass(step) { | ||||
|     case 'running': | ||||
|       return 'text-blue-400 bg-blue-100' | ||||
|     case 'error': | ||||
|       return 'text-danger bg-red-200' | ||||
|       return 'text-red-400 bg-red-200' | ||||
|     default: | ||||
|       return '' | ||||
|   } | ||||
|  | ||||
| @ -51,27 +51,12 @@ | ||||
|         <BaseInput | ||||
|           v-model.trim="mailDriverStore.mailgunConfig.mail_mailgun_secret" | ||||
|           :content-loading="isFetchingInitialData" | ||||
|           :type="getInputType" | ||||
|           type="password" | ||||
|           name="mailgun_secret" | ||||
|           autocomplete="off" | ||||
|           :invalid="v$.mailgunConfig.mail_mailgun_secret.$error" | ||||
|           @input="v$.mailgunConfig.mail_mailgun_secret.$touch()" | ||||
|         > | ||||
|           <template #right> | ||||
|             <BaseIcon | ||||
|               v-if="isShowPassword" | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeOffIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <BaseIcon | ||||
|               v-else | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </BaseInput> | ||||
|         /> | ||||
|       </BaseInputGroup> | ||||
|  | ||||
|       <BaseInputGroup | ||||
| @ -184,15 +169,6 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | ||||
| const mailDriverStore = useMailDriverStore() | ||||
| const { t } = useI18n() | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
|  | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|     mailgunConfig: { | ||||
|  | ||||
| @ -146,27 +146,12 @@ | ||||
|         <BaseInput | ||||
|           v-model.trim="mailDriverStore.sesConfig.mail_ses_secret" | ||||
|           :content-loading="isFetchingInitialData" | ||||
|           :type="getInputType" | ||||
|           type="password" | ||||
|           name="mail_ses_secret" | ||||
|           autocomplete="off" | ||||
|           :invalid="v$.sesConfig.mail_ses_secret.$error" | ||||
|           @input="v$.sesConfig.mail_ses_secret.$touch()" | ||||
|         > | ||||
|           <template #right> | ||||
|             <BaseIcon | ||||
|               v-if="isShowPassword" | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeOffIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <BaseIcon | ||||
|               v-else | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </BaseInput> | ||||
|         /> | ||||
|       </BaseInputGroup> | ||||
|     </BaseInputGrid> | ||||
|  | ||||
| @ -223,7 +208,6 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | ||||
| const mailDriverStore = useMailDriverStore() | ||||
| const { t } = useI18n() | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
| const encryptions = reactive(['tls', 'ssl', 'starttls']) | ||||
|  | ||||
| const rules = computed(() => { | ||||
| @ -264,13 +248,6 @@ const v$ = useVuelidate( | ||||
|   computed(() => mailDriverStore) | ||||
| ) | ||||
|  | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
|  | ||||
| onMounted(() => { | ||||
|   for (const key in mailDriverStore.sesConfig) { | ||||
|     if (props.configData.hasOwnProperty(key)) { | ||||
|  | ||||
| @ -58,24 +58,9 @@ | ||||
|         <BaseInput | ||||
|           v-model.trim="mailDriverStore.smtpConfig.mail_password" | ||||
|           :content-loading="isFetchingInitialData" | ||||
|           :type="getInputType" | ||||
|           type="password" | ||||
|           name="password" | ||||
|         > | ||||
|           <template #right> | ||||
|             <BaseIcon | ||||
|               v-if="isShowPassword" | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeOffIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <BaseIcon | ||||
|               v-else | ||||
|               class="mr-1 text-gray-500 cursor-pointer" | ||||
|               name="EyeIcon" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </BaseInput> | ||||
|         /> | ||||
|       </BaseInputGroup> | ||||
|  | ||||
|       <BaseInputGroup | ||||
| @ -209,17 +194,8 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | ||||
|  | ||||
| const mailDriverStore = useMailDriverStore() | ||||
| const { t } = useI18n() | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
| const encryptions = reactive(['tls', 'ssl', 'starttls']) | ||||
|  | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|     smtpConfig: { | ||||
|  | ||||
| @ -118,11 +118,11 @@ | ||||
|               " | ||||
|             > | ||||
|               {{ $t('general.actions') }} | ||||
|               <BaseIcon name="ChevronDownIcon" class="h-5" /> | ||||
|               <BaseIcon name="ChevronDownIcon"/> | ||||
|             </span> | ||||
|           </template> | ||||
|           <BaseDropdownItem @click="removeMultipleUsers"> | ||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600" /> | ||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> | ||||
|             {{ $t('general.delete') }} | ||||
|           </BaseDropdownItem> | ||||
|         </BaseDropdown> | ||||
| @ -158,7 +158,7 @@ | ||||
|         <template #cell-name="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `users/${row.data.id}/edit` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.name }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -93,6 +93,7 @@ | ||||
|                     rounded-full | ||||
|                     text-primary-500 | ||||
|                     dark:bg-gray-600 | ||||
|                     dark:text-primary-400 | ||||
|                   " | ||||
|                 > | ||||
|                   {{ initGenerator(customer.name) }} | ||||
| @ -141,6 +142,7 @@ | ||||
|                     bg-gray-200 | ||||
|                     rounded-full | ||||
|                     text-primary-500 | ||||
|                     dark:text-primary-400 | ||||
|                     dark:bg-gray-600 | ||||
|                   " | ||||
|                 > | ||||
|  | ||||
							
								
								
									
										41
									
								
								resources/scripts/components/LightDarkButton.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								resources/scripts/components/LightDarkButton.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| <template> | ||||
|    <button | ||||
|     type="button" | ||||
|     class=" | ||||
|       flex | ||||
|       h-8 | ||||
|       w-8 | ||||
|       items-center | ||||
|       justify-center | ||||
|       rounded-md | ||||
|       transition | ||||
|       hover:bg-zinc-900/5 | ||||
|       dark:hover:bg-white/5 | ||||
|     " | ||||
|     @click="onChange" | ||||
|   > | ||||
|   <BaseIcon v-if="!globalStore.isDarkModeOn" class="h-5 w-5 text-yellow-500" name="SunIcon" /> | ||||
|     <BaseIcon v-else class="h-5 w-5 text-white" name="MoonIcon" /> | ||||
|   </button> | ||||
| </template> | ||||
| <script setup> | ||||
| import { computed } from 'vue' | ||||
| import { useGlobalStore } from '@/scripts/customer/stores/global' | ||||
|  | ||||
| const globalStore = useGlobalStore() | ||||
|  | ||||
| function onChange() { | ||||
|   globalStore.isDarkModeOn = !globalStore.isDarkModeOn | ||||
|  | ||||
|   if (globalStore.isDarkModeOn) { | ||||
|     localStorage.theme = 'dark' | ||||
|     document.documentElement.classList.add('dark') | ||||
|     document.documentElement.style.setProperty('color-scheme', 'dark') | ||||
|   } else { | ||||
|     localStorage.theme = 'light' | ||||
|     document.documentElement.classList.remove('dark') | ||||
|     document.documentElement.style.setProperty('color-scheme', 'light') | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| @ -16,26 +16,28 @@ defineProps({ | ||||
|  | ||||
| const globalStore = useGlobalStore() | ||||
|  | ||||
| const enabled = ref( | ||||
|   localStorage.getItem('theme') === 'dark' || | ||||
|     document.documentElement.classList.contains('dark') | ||||
| const isDark = ref( | ||||
|   localStorage.getItem('theme') === 'dark' | ||||
|     || document.documentElement.classList.contains('dark'), | ||||
| ) | ||||
|  | ||||
| globalStore.isDarkModeOn = enabled | ||||
| globalStore.isDarkModeOn = isDark | ||||
|  | ||||
| function onChange(val) { | ||||
|   if (val) { | ||||
|     localStorage.theme = 'dark' | ||||
|     document.documentElement.classList.add('dark') | ||||
|     document.documentElement.style.setProperty('color-scheme', 'dark') | ||||
|     globalStore.isDarkModeOn = true | ||||
|   } else { | ||||
|     localStorage.theme = 'light' | ||||
|     document.documentElement.classList.remove('dark') | ||||
|     document.documentElement.style.setProperty('color-scheme', 'light') | ||||
|     globalStore.isDarkModeOn = false | ||||
|   } | ||||
| } | ||||
| const enabled = computed({ | ||||
|   get: () => globalStore.isDarkModeOn, | ||||
|   set: (value) => { | ||||
|     if (value) { | ||||
|       localStorage.theme = 'dark' | ||||
|       document.documentElement.classList.add('dark') | ||||
|       document.documentElement.style.setProperty('color-scheme', 'dark') | ||||
|     } else { | ||||
|       localStorage.theme = 'light' | ||||
|       document.documentElement.classList.remove('dark') | ||||
|       document.documentElement.style.setProperty('color-scheme', 'light') | ||||
|     } | ||||
|     globalStore.isDarkModeOn = value | ||||
|   }, | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
| @ -49,7 +51,6 @@ function onChange(val) { | ||||
|         v-model="enabled" | ||||
|         class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:ring-offset-gray-700" | ||||
|         :class="[enabled ? 'bg-primary-600' : 'bg-gray-200']" | ||||
|         @update:modelValue="onChange" | ||||
|       > | ||||
|         <span class="sr-only">Use setting</span> | ||||
|         <span | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
|       :attributes="attrs" | ||||
|       :model-config="config" | ||||
|       :masks="masks" | ||||
|       :is-dark="isDarkModeOn" | ||||
|       :locale="global.locale" | ||||
|     > | ||||
|       <template | ||||
| @ -72,7 +73,7 @@ | ||||
|  | ||||
|       <template v-if="showExtraOptions" #footer> | ||||
|         <div | ||||
|           class="bg-gray-100 grid grid-cols-3 gap-2 p-2 border-t rounded-b-lg" | ||||
|           class="bg-gray-100 dark:bg-gray-800 grid grid-cols-3 gap-2 p-2 border-t dark:border-gray-500 rounded-b-lg" | ||||
|         > | ||||
|           <button type="button" class="extra-button" @click="moveToDate(sourceDate)"> | ||||
|             {{ global.t('date_picker.same_day') }} | ||||
| @ -146,7 +147,7 @@ const props = defineProps({ | ||||
|   defaultInputClass: { | ||||
|     type: String, | ||||
|     default: | ||||
|       'border-2 font-base pl-8 py-2 outline-none focus:ring-primary-400 focus:outline-none focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black', | ||||
|       'border-2 dark:bg-gray-700 dark:border-gray-600 dark:text-white font-base pl-8 py-2 outline-none focus:ring-primary-400 focus:outline-none focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black', | ||||
|   }, | ||||
|   time24hr: { | ||||
|     type: Boolean, | ||||
| @ -163,7 +164,7 @@ const props = defineProps({ | ||||
|   sourceDate: { | ||||
|     type: [String, Date], | ||||
|     default: () => new Date(), | ||||
|   } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| const emit = defineEmits(['update:modelValue']) | ||||
| @ -175,6 +176,9 @@ const vCalendar = ref(null) | ||||
| const hasIconSlot = computed(() => { | ||||
|   return !!slots.icon | ||||
| }) | ||||
| const isDarkModeOn = computed(() => | ||||
|   document.documentElement.classList.contains('dark') | ||||
| ) | ||||
|  | ||||
| const computedContainerClass = computed(() => { | ||||
|   let containerClass = `${props.containerClass} ` | ||||
|  | ||||
| @ -90,7 +90,7 @@ | ||||
|  | ||||
|     <input | ||||
|       v-bind="$attrs" | ||||
|       :type="type" | ||||
|       :type="getType" | ||||
|       :value="modelValue" | ||||
|       :disabled="disabled" | ||||
|       :class="[ | ||||
| @ -144,6 +144,44 @@ | ||||
|     > | ||||
|       <slot name="right" :class="iconRightClass" /> | ||||
|     </div> | ||||
|     <div | ||||
|       v-if="loading && loadingPosition === 'right'" class=" | ||||
|         absolute | ||||
|         inset-y-0 | ||||
|         right-0 | ||||
|         flex | ||||
|         items-center | ||||
|         pr-3 | ||||
|         pointer-events-none | ||||
|       " | ||||
|     > | ||||
|       <svg | ||||
|         class="animate-spin !text-primary-500" :class="[iconRightClass]" xmlns="http://www.w3.org/2000/svg" | ||||
|         fill="none" viewBox="0 0 24 24" | ||||
|       > | ||||
|         <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" /> | ||||
|         <path | ||||
|           class="opacity-75" fill="currentColor" | ||||
|           d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" | ||||
|         /> | ||||
|       </svg> | ||||
|     </div> | ||||
|  | ||||
|     <div v-if="hasRightIconSlot" class="absolute inset-y-0 right-0 flex items-center pr-3"> | ||||
|       <slot name="right" :class="iconRightClass" /> | ||||
|     </div> | ||||
|  | ||||
|     <div v-if="type == 'password'" class="absolute inset-y-0 right-0 flex items-center pr-3"> | ||||
|       <a | ||||
|         v-if="isShowPassword" href="#" class="block" data-cy="eye" tabindex="-1" | ||||
|         @click.prevent="isShowPassword = !isShowPassword" | ||||
|       > | ||||
|         <BaseIcon name="EyeOffIcon" class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" /> | ||||
|       </a> | ||||
|       <a v-else href="#" class="block" data-cy="eye" tabindex="-1" @click.prevent="isShowPassword = !isShowPassword"> | ||||
|         <BaseIcon name="EyeIcon" class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" /> | ||||
|       </a> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -219,6 +257,15 @@ const slots = useSlots() | ||||
|  | ||||
| const emit = defineEmits(['update:modelValue']) | ||||
|  | ||||
| const isShowPassword = ref(false) | ||||
|  | ||||
| const getType = computed(() => { | ||||
|   if (props.type === 'password') | ||||
|     return isShowPassword.value ? 'text' : 'password' | ||||
|  | ||||
|   return props.type | ||||
| }) | ||||
|  | ||||
| const hasLeftIconSlot = computed(() => { | ||||
|   return !!slots.left || (props.loading && props.loadingPosition === 'left') | ||||
| }) | ||||
|  | ||||
| @ -1,16 +1,7 @@ | ||||
| <template> | ||||
|   <div | ||||
|     :class="containerClass" | ||||
|     class=" | ||||
|       relative | ||||
|       after:bg-gray-200 | ||||
|       after:absolute | ||||
|       after:transform | ||||
|       after:top-1/2 | ||||
|       after:-translate-y-1/2 | ||||
|       after:h-2 | ||||
|       after:w-full | ||||
|     " | ||||
|     class="relative after:bg-gray-200 dark:after:bg-gray-700 after:absolute after:transform after:top-1/2 after:-translate-y-1/2 after:h-2 after:w-full" | ||||
|   > | ||||
|     <a | ||||
|       v-for="(number, index) in steps" | ||||
| @ -58,21 +49,21 @@ export default { | ||||
|     }, | ||||
|     currentStepClass: { | ||||
|       type: String, | ||||
|       default: 'bg-white border-primary-500', | ||||
|       default: 'bg-white border-primary-500 dark:bg-gray-600 dark:border-gray-500 dark:border-primary-600', | ||||
|     }, | ||||
|     nextStepClass: { | ||||
|       type: String, | ||||
|       default: 'border-gray-200 bg-white', | ||||
|       default: 'border-gray-200 bg-white dark:bg-gray-600 dark:border-gray-500', | ||||
|     }, | ||||
|     previousStepClass: { | ||||
|       type: String, | ||||
|       default: | ||||
|         'bg-primary-500 border-primary-500 flex justify-center items-center', | ||||
|         'bg-primary-500 dark:bg-primary-600 border-primary-500 flex justify-center items-center dark:border-primary-600', | ||||
|     }, | ||||
|     iconClass: { | ||||
|       type: String, | ||||
|       default: | ||||
|         'flex items-center justify-center w-full h-full text-sm font-black text-center text-white', | ||||
|         'flex items-center justify-center w-full h-full text-sm font-black text-center text-white dark:text-gray-400', | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
|       </p> | ||||
|     </div> | ||||
|     <slot /> | ||||
|     <BaseDarkHighlight class="z-[-1]"/> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -25,16 +26,16 @@ const props = defineProps({ | ||||
|   stepContainerClass: { | ||||
|     type: String, | ||||
|     default: | ||||
|       'w-full p-8 mb-8 bg-white border border-gray-200 border-solid rounded', | ||||
|       'w-full p-8 mb-8 bg-white border border-gray-200 border-solid rounded dark:from-gray-700/70 dark:to-gray-800/70 dark:bg-transparent dark:backdrop-blur-xl dark:shadow-glass dark:border dark:border-white/10', | ||||
|   }, | ||||
|   stepTitleClass: { | ||||
|     type: String, | ||||
|     default: 'text-2xl not-italic font-semibold leading-7 text-black', | ||||
|     default: 'text-2xl not-italic font-semibold leading-7 text-black dark:text-white', | ||||
|   }, | ||||
|   stepDescriptionClass: { | ||||
|     type: String, | ||||
|     default: | ||||
|       'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-gray-500 lg:w-7/12 md:w-7/12 sm:w-7/12', | ||||
|       'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-gray-500 dark:text-gray-300 lg:w-7/12 md:w-7/12 sm:w-7/12', | ||||
|   }, | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
|     <path | ||||
|       d="M690 4.08004C518 -9.91998 231 4.08004 -6 176.361L231 197.08L1170 219.08C1113.33 175.747 909.275 21.928 690 4.08004Z" | ||||
|       fill="white" | ||||
|       class="dark:fill-gray-900" | ||||
|       fill-opacity="0.1" | ||||
|     /> | ||||
|   </svg> | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  | ||||
|     <!-- <SiteSidebar /> --> | ||||
|  | ||||
|     <main class="mt-16 pb-16 h-screen overflow-y-auto min-h-0"> | ||||
|     <main class="h-screen min-h-0 pb-16 mt-16 overflow-y-auto"> | ||||
|       <router-view /> | ||||
|     </main> | ||||
|   </div> | ||||
|  | ||||
| @ -1,31 +1,24 @@ | ||||
| <template> | ||||
|   <div | ||||
|     class=" | ||||
|       min-h-screen | ||||
|       bg-gray-200 | ||||
|       flex flex-col | ||||
|       justify-center | ||||
|       py-12 | ||||
|       sm:px-6 | ||||
|       lg:px-8 | ||||
|     " | ||||
|     class="flex flex-col justify-center h-full min-h-screen py-12 overflow-hidden bg-gray-100 sm:px-6 lg:px-8 dark:bg-gray-800/80 dark:text-white font-base " | ||||
|   > | ||||
|     <NotificationRoot /> | ||||
|  | ||||
|     <div class="sm:mx-auto sm:w-full sm:max-w-md px-4 sm:px-0"> | ||||
|     <div class="px-4 sm:mx-auto sm:w-full sm:max-w-md sm:px-0"> | ||||
|       <MainLogo | ||||
|         v-if="!customerLogo" | ||||
|         class="block w-48 h-auto max-w-full text-primary-400 mx-auto" | ||||
|         class="block w-48 h-auto max-w-full mx-auto text-primary-400" | ||||
|       /> | ||||
|       <img | ||||
|         v-else | ||||
|         :src="customerLogo" | ||||
|         class="block w-48 h-auto max-w-full text-primary-400 mx-auto" | ||||
|         class="block w-48 h-auto max-w-full mx-auto text-primary-400" | ||||
|       /> | ||||
|     </div> | ||||
|  | ||||
|     <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md px-4 sm:px-0"> | ||||
|       <div class="bg-white py-8 px-4 shadow rounded-lg sm:px-10"> | ||||
|     <div class="px-4 mt-8 sm:mx-auto sm:w-full sm:max-w-md sm:px-0"> | ||||
|       <div class="px-4 py-8 bg-white rounded-lg shadow sm:px-10 dark:from-gray-700/70 dark:to-gray-800/70 dark:bg-transparent dark:backdrop-blur-xl dark:shadow-glass dark:border dark:border-white/10"> | ||||
|       <BaseDarkHighlight/> | ||||
|         <router-view /> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
| @ -34,7 +34,7 @@ | ||||
|               :to="`/${globalStore.companySlug}${item.link}`" | ||||
|               :class="[ | ||||
|                 hasActiveUrl(item.link) | ||||
|                   ? 'border-primary-500 text-primary-600 dark:text-primary-400' | ||||
|                   ? 'text-primary-600 border-primary-600 dark:border-primary-400 dark:text-primary-400' | ||||
|                   : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-200', | ||||
|                 'inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium', | ||||
|               ]" | ||||
| @ -44,6 +44,8 @@ | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="hidden sm:ml-6 sm:flex sm:items-center"> | ||||
|           <!-- Dark mode Toggle --> | ||||
|           <LightDarkButton/> | ||||
|  | ||||
|           <!-- Profile dropdown --> | ||||
|  | ||||
| @ -134,18 +136,22 @@ | ||||
|         </router-link> | ||||
|       </div> | ||||
|       <div class="pt-4 pb-3 border-t border-gray-200 dark:border-gray-500"> | ||||
|         <div class="flex items-center px-4"> | ||||
|           <div class="shrink-0"> | ||||
|             <img class="h-10 w-10 rounded-full" :src="previewAvatar" alt="" /> | ||||
|           </div> | ||||
|           <div class="ml-3"> | ||||
|             <div class="text-base font-medium text-gray-800"> | ||||
|               {{ globalStore.currentUser.title }} | ||||
|         <div class="flex items-center justify-between pr-5"> | ||||
|           <div class="flex items-center px-4"> | ||||
|             <div class="shrink-0"> | ||||
|               <img class="h-10 w-10 rounded-full" :src="previewAvatar" alt="" /> | ||||
|             </div> | ||||
|             <div class="text-sm font-medium text-gray-500 dark:text-gray-200"> | ||||
|               {{ globalStore.currentUser.email }} | ||||
|             <div class="ml-3"> | ||||
|               <div class="text-base font-medium text-gray-800"> | ||||
|                 {{ globalStore.currentUser.title }} | ||||
|               </div> | ||||
|               <div class="text-sm font-medium text-gray-500 dark:text-gray-200"> | ||||
|                 {{ globalStore.currentUser.email }} | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|           <!-- Dark mode Toggle --> | ||||
|           <LightDarkButton/> | ||||
|         </div> | ||||
|         <div class="mt-3 space-y-1"> | ||||
|           <router-link | ||||
| @ -172,6 +178,7 @@ import { useRoute, useRouter } from 'vue-router' | ||||
| import { ref, watch, computed } from 'vue' | ||||
| import { useGlobalStore } from '@/scripts/customer/stores/global' | ||||
| import MainLogo from '@/scripts/components/icons/MainLogo.vue' | ||||
| import LightDarkButton from '@/scripts/components/LightDarkButton.vue' | ||||
| import { | ||||
|   Disclosure, | ||||
|   DisclosureButton, | ||||
|  | ||||
| @ -13,7 +13,8 @@ export const useGlobalStore = defineStore({ | ||||
|     currentUser: null, | ||||
|     companySlug: '', | ||||
|     mainMenu: null, | ||||
|     enabledModules: [] | ||||
|     enabledModules: [], | ||||
|     isDarkModeOn: localStorage.getItem('theme') === 'dark' || document.documentElement.classList.contains('dark') | ||||
|   }), | ||||
|  | ||||
|   actions: { | ||||
|  | ||||
| @ -31,7 +31,7 @@ | ||||
|     <div class="mt-4 mb-4 text-sm"> | ||||
|       <router-link | ||||
|         to="login" | ||||
|         class="text-sm text-primary-400 hover:text-gray-700" | ||||
|         class="text-sm text-primary-400 hover:text-gray-700 dark:hover:text-primary-500" | ||||
|       > | ||||
|         {{ $t('general.back_to_login') }} | ||||
|       </router-link> | ||||
|  | ||||
| @ -32,30 +32,15 @@ | ||||
|     > | ||||
|       <BaseInput | ||||
|         v-model="authStore.loginData.password" | ||||
|         :type="getInputType" | ||||
|         :invalid="v$.loginData.password.$error" | ||||
|         type="password" | ||||
|         @input="v$.loginData.password.$touch()" | ||||
|       > | ||||
|         <template #right> | ||||
|           <BaseIcon | ||||
|             v-if="isShowPassword" | ||||
|             name="EyeOffIcon" | ||||
|             class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|             @click="isShowPassword = !isShowPassword" | ||||
|           /> | ||||
|           <BaseIcon | ||||
|             v-else | ||||
|             name="EyeIcon" | ||||
|             class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|             @click="isShowPassword = !isShowPassword" | ||||
|           /> | ||||
|         </template> | ||||
|       </BaseInput> | ||||
|       /> | ||||
|     </BaseInputGroup> | ||||
|     <div class="flex items-center justify-between"> | ||||
|       <router-link | ||||
|         :to="{ name: 'customer.forgot-password' }" | ||||
|         class="text-sm text-primary-600 hover:text-gray-500" | ||||
|         class="text-sm text-primary-400 hover:text-gray-500 dark:hover:text-primary-500" | ||||
|       > | ||||
|         {{ $t('login.forgot_password') }} | ||||
|       </router-link> | ||||
| @ -91,14 +76,6 @@ const authStore = useAuthStore() | ||||
| const { t } = useI18n() | ||||
|  | ||||
| let isLoading = ref(false) | ||||
| const isShowPassword = ref(false) | ||||
|  | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|  | ||||
| @ -23,23 +23,11 @@ | ||||
|     > | ||||
|       <BaseInput | ||||
|         v-model="loginData.password" | ||||
|         :type="isShowPassword ? 'text' : 'password'" | ||||
|         type="password" | ||||
|         name="password" | ||||
|         :invalid="v$.password.$error" | ||||
|         @input="v$.password.$touch()" | ||||
|       > | ||||
|         <template #right> | ||||
|           <EyeOffIcon | ||||
|             v-if="isShowPassword" | ||||
|             class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|             @click="isShowPassword = !isShowPassword" | ||||
|           /> | ||||
|           <EyeIcon | ||||
|             v-else | ||||
|             class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|             @click="isShowPassword = !isShowPassword" | ||||
|           /> </template | ||||
|       ></BaseInput> | ||||
|       /> | ||||
|     </BaseInputGroup> | ||||
|  | ||||
|     <BaseInputGroup | ||||
| @ -93,7 +81,6 @@ const loginData = reactive({ | ||||
|  | ||||
| const globalStore = useGlobalStore() | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
| let isLoading = ref(false) | ||||
|  | ||||
| const rules = computed(() => { | ||||
|  | ||||
| @ -26,7 +26,7 @@ | ||||
|             :to="{ | ||||
|               path: `/${globalStore.companySlug}/customer/invoices/${row.data.id}/view`, | ||||
|             }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.invoice_number }} | ||||
|           </router-link> | ||||
| @ -73,7 +73,7 @@ | ||||
|             :to="{ | ||||
|               path: `/${globalStore.companySlug}/customer/estimates/${row.data.id}/view`, | ||||
|             }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.estimate_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -100,7 +100,7 @@ | ||||
|         <template #cell-estimate_number="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `estimates/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.estimate_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -95,7 +95,7 @@ | ||||
|         <template #cell-invoice_number="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `invoices/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.invoice_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -78,7 +78,7 @@ | ||||
|             :to="{ | ||||
|               path: `payments/${row.data.id}/view`, | ||||
|             }" | ||||
|             class="font-medium text-primary-500" | ||||
|             class="font-medium text-primary-500 dark:text-primary-400" | ||||
|           > | ||||
|             {{ row.data.payment_number }} | ||||
|           </router-link> | ||||
|  | ||||
| @ -66,24 +66,10 @@ | ||||
|         > | ||||
|           <BaseInput | ||||
|             v-model="userStore.userForm.password" | ||||
|             :type="isShowPassword ? 'text' : 'password'" | ||||
|             type="password" | ||||
|             :invalid="v$.userForm.password.$error" | ||||
|             @input="v$.userForm.password.$touch()" | ||||
|           > | ||||
|             <template #right> | ||||
|               <BaseIcon | ||||
|                 v-if="isShowPassword" | ||||
|                 name="EyeOffIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowPassword = !isShowPassword" | ||||
|               /> | ||||
|               <BaseIcon | ||||
|                 v-else | ||||
|                 name="EyeIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowPassword = !isShowPassword" | ||||
|               /> </template | ||||
|           ></BaseInput> | ||||
|           /> | ||||
|         </BaseInputGroup> | ||||
|  | ||||
|         <BaseInputGroup | ||||
| @ -95,24 +81,10 @@ | ||||
|         > | ||||
|           <BaseInput | ||||
|             v-model="userStore.userForm.confirm_password" | ||||
|             :type="isShowConfirmPassword ? 'text' : 'password'" | ||||
|             type="password" | ||||
|             :invalid="v$.userForm.confirm_password.$error" | ||||
|             @input="v$.userForm.confirm_password.$touch()" | ||||
|           > | ||||
|             <template #right> | ||||
|               <BaseIcon | ||||
|                 v-if="isShowConfirmPassword" | ||||
|                 name="EyeOffIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowConfirmPassword = !isShowConfirmPassword" | ||||
|               /> | ||||
|               <BaseIcon | ||||
|                 v-else | ||||
|                 name="EyeIcon" | ||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|                 @click="isShowConfirmPassword = !isShowConfirmPassword" | ||||
|               /> </template | ||||
|           ></BaseInput> | ||||
|           /> | ||||
|         </BaseInputGroup> | ||||
|       </div> | ||||
|  | ||||
| @ -151,8 +123,6 @@ const { t, tm } = useI18n() | ||||
| let imgFiles = ref([]) | ||||
| let isSaving = ref(false) | ||||
| let avatarFileBlob = ref(null) | ||||
| let isShowPassword = ref(false) | ||||
| let isShowConfirmPassword = ref(false) | ||||
| const isCustomerAvatarRemoved = ref(false) | ||||
|  | ||||
| if (userStore.userForm.avatar) { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	