mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-28 12:11:08 -04:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			dark-switc
			...
			dark-cust-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3e15aca9ef | |||
| 1b31f21099 | |||
| be0433281d | 
| @ -30,22 +30,7 @@ | |||||||
|         <template v-if="userStore.hasAbilities(ability)" #action> |         <template v-if="userStore.hasAbilities(ability)" #action> | ||||||
|           <button |           <button | ||||||
|             type="button" |             type="button" | ||||||
|             class=" |             class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none cursor-pointer " | ||||||
|               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" |             @click="openTaxModal" | ||||||
|           > |           > | ||||||
|             <BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" /> |             <BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" /> | ||||||
| @ -68,7 +53,7 @@ | |||||||
|       <BaseIcon |       <BaseIcon | ||||||
|         v-if="taxes.length && index !== taxes.length - 1" |         v-if="taxes.length && index !== taxes.length - 1" | ||||||
|         name="TrashIcon" |         name="TrashIcon" | ||||||
|         class="h-5 text-gray-700 dark:text-red-400 cursor-pointer" |         class="h-5 text-gray-700 cursor-pointer" | ||||||
|         @click="removeTax(index)" |         @click="removeTax(index)" | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
|  | |||||||
| @ -15,26 +15,12 @@ | |||||||
|       <thead |       <thead | ||||||
|         class=" |         class=" | ||||||
|           bg-white |           bg-white | ||||||
|           border |           border border-gray-200 border-solid | ||||||
|           border-gray-200 |  | ||||||
|           border-solid |  | ||||||
|           dark:shadow-glass dark:border dark:border-white/10 dark:bg-gray-800/70 |           dark:shadow-glass dark:border dark:border-white/10 dark:bg-gray-800/70 | ||||||
|         " |           " | ||||||
|       > |         > | ||||||
|         <tr> |         <tr> | ||||||
|           <th |           <th class="text-left" :class="theadClass"> | ||||||
|             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"> |             <BaseContentPlaceholders v-if="isLoading"> | ||||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> |               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||||
|             </BaseContentPlaceholders> |             </BaseContentPlaceholders> | ||||||
| @ -42,19 +28,7 @@ | |||||||
|               {{ $tc('items.item', 2) }} |               {{ $tc('items.item', 2) }} | ||||||
|             </span> |             </span> | ||||||
|           </th> |           </th> | ||||||
|           <th |           <th class="text-right" :class="theadClass"> | ||||||
|             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"> |             <BaseContentPlaceholders v-if="isLoading"> | ||||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> |               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||||
|             </BaseContentPlaceholders> |             </BaseContentPlaceholders> | ||||||
| @ -62,19 +36,7 @@ | |||||||
|               {{ $t('invoices.item.quantity') }} |               {{ $t('invoices.item.quantity') }} | ||||||
|             </span> |             </span> | ||||||
|           </th> |           </th> | ||||||
|           <th |           <th class="text-left" :class="theadClass"> | ||||||
|             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"> |             <BaseContentPlaceholders v-if="isLoading"> | ||||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> |               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||||
|             </BaseContentPlaceholders> |             </BaseContentPlaceholders> | ||||||
| @ -83,18 +45,9 @@ | |||||||
|             </span> |             </span> | ||||||
|           </th> |           </th> | ||||||
|           <th |           <th | ||||||
|             v-if="store[storeProp].discount_per_item === 'YES'" |             v-if="store[storeProp].discount_per_item_enabled" | ||||||
|             class=" |             class="text-left" | ||||||
|               px-5 |             :class="theadClass" | ||||||
|               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"> |             <BaseContentPlaceholders v-if="isLoading"> | ||||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> |               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||||
| @ -103,19 +56,7 @@ | |||||||
|               {{ $t('invoices.item.discount') }} |               {{ $t('invoices.item.discount') }} | ||||||
|             </span> |             </span> | ||||||
|           </th> |           </th> | ||||||
|           <th |           <th class="text-right" :class="theadClass"> | ||||||
|             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"> |             <BaseContentPlaceholders v-if="isLoading"> | ||||||
|               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> |               <BaseContentPlaceholdersText :lines="1" class="w-16 h-5" /> | ||||||
|             </BaseContentPlaceholders> |             </BaseContentPlaceholders> | ||||||
| @ -197,6 +138,11 @@ const props = defineProps({ | |||||||
|     type: String, |     type: String, | ||||||
|     default: '', |     default: '', | ||||||
|   }, |   }, | ||||||
|  |   theadClass: { | ||||||
|  |     type: String, | ||||||
|  |     default: `px-5 py-3 text-sm not-italic font-medium leading-5 | ||||||
|  |               text-gray-700 border-t border-b border-gray-200 border-solid dark:text-white dark:border-white/10` | ||||||
|  |   }, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const companyStore = useCompanyStore() | const companyStore = useCompanyStore() | ||||||
|  | |||||||
| @ -40,7 +40,6 @@ | |||||||
|             px-4 |             px-4 | ||||||
|             md:px-8 |             md:px-8 | ||||||
|             py-1.5 |             py-1.5 | ||||||
|             dark:text-gray-200 |  | ||||||
|           " |           " | ||||||
|         > |         > | ||||||
|           {{ $tc('settings.roles.permission', 2) }} |           {{ $tc('settings.roles.permission', 2) }} | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="h-screen overflow-y-auto text-base dark:bg-gray-800/80 dark:text-white"> |   <div class="h-screen overflow-y-auto text-base"> | ||||||
|     <NotificationRoot /> |     <NotificationRoot /> | ||||||
|  |  | ||||||
|     <div class="container px-4 mx-auto"> |     <div class="container mx-auto px-4"> | ||||||
|       <router-view /> |       <router-view /> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
|  | |||||||
| @ -68,8 +68,10 @@ | |||||||
|           </TransitionChild> |           </TransitionChild> | ||||||
|           <div class="flex-1 h-0 pt-5 pb-4 overflow-y-auto"> |           <div class="flex-1 h-0 pt-5 pb-4 overflow-y-auto"> | ||||||
|             <div class="flex items-center shrink-0 px-4 mb-10"> |             <div class="flex items-center shrink-0 px-4 mb-10"> | ||||||
|               <img class="h-auto max-w-full w-36 hidden dark:block" :src="getDarkLogo"/> |               <MainLogo | ||||||
|               <img class="h-auto max-w-full w-36 block dark:hidden" :src="getLightLogo"/> |                 class="block h-auto max-w-full w-36 text-primary-400" | ||||||
|  |                 alt="Crater Logo" | ||||||
|  |               /> | ||||||
|             </div> |             </div> | ||||||
|  |  | ||||||
|             <nav |             <nav | ||||||
| @ -93,7 +95,7 @@ | |||||||
|                   :name="item.icon" |                   :name="item.icon" | ||||||
|                   :class="[ |                   :class="[ | ||||||
|                     hasActiveUrl(item.link) |                     hasActiveUrl(item.link) | ||||||
|                       ? 'text-primary-500 dark:text-primary-400' |                       ? 'text-primary-500 ' | ||||||
|                       : 'text-gray-400', |                       : 'text-gray-400', | ||||||
|                     'mr-4 shrink-0 h-5 w-5', |                     'mr-4 shrink-0 h-5 w-5', | ||||||
|                   ]" |                   ]" | ||||||
| @ -149,7 +151,7 @@ | |||||||
|           :name="item.icon" |           :name="item.icon" | ||||||
|           :class="[ |           :class="[ | ||||||
|             hasActiveUrl(item.link) |             hasActiveUrl(item.link) | ||||||
|               ? 'text-primary-500 dark:text-primary-400' |               ? 'text-primary-500 group-hover:text-primary-500 dark:text-primary-400 dark:group-hover:text-primary-500 ' | ||||||
|               : 'text-gray-400 group-hover:text-black dark:text-gray-400 dark:group-hover:text-white', |               : 'text-gray-400 group-hover:text-black dark:text-gray-400 dark:group-hover:text-white', | ||||||
|             'mr-4 shrink-0 h-5 w-5 ', |             'mr-4 shrink-0 h-5 w-5 ', | ||||||
|           ]" |           ]" | ||||||
| @ -165,7 +167,8 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup> | <script setup> | ||||||
| import { computed } from 'vue' | import MainLogo from '@/scripts/components/icons/MainLogo.vue' | ||||||
|  |  | ||||||
| import { | import { | ||||||
|   Dialog, |   Dialog, | ||||||
|   DialogOverlay, |   DialogOverlay, | ||||||
| @ -180,9 +183,6 @@ import LightDarkSwitch from '@/scripts/components/LightDarkSwitcher.vue' | |||||||
| const route = useRoute() | const route = useRoute() | ||||||
| const globalStore = useGlobalStore() | 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) { | function hasActiveUrl(url) { | ||||||
|   return route.path.indexOf(url) > -1 |   return route.path.indexOf(url) > -1 | ||||||
| } | } | ||||||
|  | |||||||
| @ -34,7 +34,8 @@ export const useGlobalStore = (useWindow = false) => { | |||||||
|       isAppLoaded: false, |       isAppLoaded: false, | ||||||
|       isSidebarOpen: false, |       isSidebarOpen: false, | ||||||
|       areCurrenciesLoading: false, |       areCurrenciesLoading: false, | ||||||
|       isDarkModeOn: localStorage.getItem('theme') === 'dark' || document.documentElement.classList.contains('dark'), |       isDarkModeOn: false, | ||||||
|  |  | ||||||
|       downloadReport: null, |       downloadReport: null, | ||||||
|     }), |     }), | ||||||
|  |  | ||||||
|  | |||||||
| @ -113,7 +113,7 @@ | |||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|           <BaseDropdownItem @click="removeMultipleCustomers"> |           <BaseDropdownItem @click="removeMultipleCustomers"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -154,7 +154,7 @@ | |||||||
|               :text="row.data.name" |               :text="row.data.name" | ||||||
|               :length="30" |               :length="30" | ||||||
|               tag="span" |               tag="span" | ||||||
|               class="font-medium text-primary-500 flex flex-col dark:text-primary-400" |               class="font-medium text-primary-500 flex flex-col" | ||||||
|             /> |             /> | ||||||
|             <BaseText |             <BaseText | ||||||
|               :text="row.data.contact_name ? row.data.contact_name : ''" |               :text="row.data.contact_name ? row.data.contact_name : ''" | ||||||
|  | |||||||
| @ -34,8 +34,8 @@ | |||||||
|             v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)" |             v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)" | ||||||
|             :to="`/admin/estimates/create?customer=${$route.params.id}`" |             :to="`/admin/estimates/create?customer=${$route.params.id}`" | ||||||
|           > |           > | ||||||
|             <BaseDropdownItem v-slot="slotProps"> |             <BaseDropdownItem class=""> | ||||||
|               <BaseIcon name="DocumentIcon" :class="slotProps.class" /> |               <BaseIcon name="DocumentIcon" class="mr-3 text-gray-600" /> | ||||||
|               {{ $t('estimates.new_estimate') }} |               {{ $t('estimates.new_estimate') }} | ||||||
|             </BaseDropdownItem> |             </BaseDropdownItem> | ||||||
|           </router-link> |           </router-link> | ||||||
| @ -44,8 +44,8 @@ | |||||||
|             v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)" |             v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)" | ||||||
|             :to="`/admin/invoices/create?customer=${$route.params.id}`" |             :to="`/admin/invoices/create?customer=${$route.params.id}`" | ||||||
|           > |           > | ||||||
|             <BaseDropdownItem v-slot="slotProps"> |             <BaseDropdownItem> | ||||||
|               <BaseIcon name="DocumentTextIcon" :class="slotProps.class" /> |               <BaseIcon name="DocumentTextIcon" class="mr-3 text-gray-600" /> | ||||||
|               {{ $t('invoices.new_invoice') }} |               {{ $t('invoices.new_invoice') }} | ||||||
|             </BaseDropdownItem> |             </BaseDropdownItem> | ||||||
|           </router-link> |           </router-link> | ||||||
| @ -54,8 +54,8 @@ | |||||||
|             v-if="userStore.hasAbilities(abilities.CREATE_PAYMENT)" |             v-if="userStore.hasAbilities(abilities.CREATE_PAYMENT)" | ||||||
|             :to="`/admin/payments/create?customer=${$route.params.id}`" |             :to="`/admin/payments/create?customer=${$route.params.id}`" | ||||||
|           > |           > | ||||||
|             <BaseDropdownItem v-slot="slotProps"> |             <BaseDropdownItem> | ||||||
|               <BaseIcon name="CreditCardIcon" :class="slotProps.class" /> |               <BaseIcon name="CreditCardIcon" class="mr-3 text-gray-600" /> | ||||||
|               {{ $t('payments.new_payment') }} |               {{ $t('payments.new_payment') }} | ||||||
|             </BaseDropdownItem> |             </BaseDropdownItem> | ||||||
|           </router-link> |           </router-link> | ||||||
| @ -64,8 +64,8 @@ | |||||||
|             v-if="userStore.hasAbilities(abilities.CREATE_EXPENSE)" |             v-if="userStore.hasAbilities(abilities.CREATE_EXPENSE)" | ||||||
|             :to="`/admin/expenses/create?customer=${$route.params.id}`" |             :to="`/admin/expenses/create?customer=${$route.params.id}`" | ||||||
|           > |           > | ||||||
|             <BaseDropdownItem v-slot="slotProps"> |             <BaseDropdownItem> | ||||||
|               <BaseIcon name="CalculatorIcon" :class="slotProps.class" /> |               <BaseIcon name="CalculatorIcon" class="mr-3 text-gray-600" /> | ||||||
|               {{ $t('expenses.new_expense') }} |               {{ $t('expenses.new_expense') }} | ||||||
|             </BaseDropdownItem> |             </BaseDropdownItem> | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -13,7 +13,6 @@ | |||||||
|       xl:ml-64 |       xl:ml-64 | ||||||
|       w-88 |       w-88 | ||||||
|       xl:block |       xl:block | ||||||
|       dark:bg-gray-800 |  | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <div |     <div | ||||||
| @ -26,7 +25,6 @@ | |||||||
|         pb-2 |         pb-2 | ||||||
|         border border-gray-200 border-solid |         border border-gray-200 border-solid | ||||||
|         height-full |         height-full | ||||||
|         dark:border-gray-600 |  | ||||||
|       " |       " | ||||||
|     > |     > | ||||||
|       <BaseInput |       <BaseInput | ||||||
| @ -61,7 +59,6 @@ | |||||||
|               mb-2 |               mb-2 | ||||||
|               text-sm |               text-sm | ||||||
|               border-b border-gray-200 border-solid |               border-b border-gray-200 border-solid | ||||||
|               dark:border-gray-600 |  | ||||||
|             " |             " | ||||||
|           > |           > | ||||||
|             {{ $t('general.sort_by') }} |             {{ $t('general.sort_by') }} | ||||||
| @ -117,7 +114,6 @@ | |||||||
|         border-l border-gray-200 border-solid |         border-l border-gray-200 border-solid | ||||||
|         sidebar |         sidebar | ||||||
|         base-scroll |         base-scroll | ||||||
|         dark:border-gray-600 |  | ||||||
|       " |       " | ||||||
|     > |     > | ||||||
|       <div v-for="(customer, index) in customerList" :key="index"> |       <div v-for="(customer, index) in customerList" :key="index"> | ||||||
| @ -126,9 +122,9 @@ | |||||||
|           :id="'customer-' + customer.id" |           :id="'customer-' + customer.id" | ||||||
|           :to="`/admin/customers/${customer.id}/view`" |           :to="`/admin/customers/${customer.id}/view`" | ||||||
|           :class="[ |           :class="[ | ||||||
|             'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent dark:hover:bg-gray-700', |             'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent', | ||||||
|             { |             { | ||||||
|               'bg-gray-100 border-l-4 border-primary-500 border-solid dark:border-primary-400 dark:bg-gray-700': |               'bg-gray-100 border-l-4 border-primary-500 border-solid': | ||||||
|                 hasActiveUrl(customer.id), |                 hasActiveUrl(customer.id), | ||||||
|             }, |             }, | ||||||
|           ]" |           ]" | ||||||
| @ -147,7 +143,6 @@ | |||||||
|                 text-black |                 text-black | ||||||
|                 capitalize |                 capitalize | ||||||
|                 truncate |                 truncate | ||||||
|                 dark:text-white |  | ||||||
|               " |               " | ||||||
|             /> |             /> | ||||||
|  |  | ||||||
| @ -162,7 +157,6 @@ | |||||||
|                 font-medium |                 font-medium | ||||||
|                 leading-5 |                 leading-5 | ||||||
|                 text-gray-600 |                 text-gray-600 | ||||||
|                 dark:text-gray-400 |  | ||||||
|               " |               " | ||||||
|             /> |             /> | ||||||
|           </div> |           </div> | ||||||
| @ -181,7 +175,7 @@ | |||||||
|       </div> |       </div> | ||||||
|       <p |       <p | ||||||
|         v-if="!customerList?.length && !isFetching" |         v-if="!customerList?.length && !isFetching" | ||||||
|         class="flex justify-center px-4 mt-5 text-sm text-gray-600 dark:text-gray-300" |         class="flex justify-center px-4 mt-5 text-sm text-gray-600" | ||||||
|       > |       > | ||||||
|         {{ $t('customers.no_matching_customers') }} |         {{ $t('customers.no_matching_customers') }} | ||||||
|       </p> |       </p> | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ | |||||||
|           <template #cell-user="{ row }"> |           <template #cell-user="{ row }"> | ||||||
|             <router-link |             <router-link | ||||||
|               :to="{ path: `invoices/${row.data.id}/view` }" |               :to="{ path: `invoices/${row.data.id}/view` }" | ||||||
|               class="font-medium text-primary-500 dark:text-primary-400" |               class="font-medium text-primary-500" | ||||||
|             > |             > | ||||||
|               {{ row.data.customer.name }} |               {{ row.data.customer.name }} | ||||||
|             </router-link> |             </router-link> | ||||||
| @ -78,7 +78,7 @@ | |||||||
|           <template #cell-user="{ row }"> |           <template #cell-user="{ row }"> | ||||||
|             <router-link |             <router-link | ||||||
|               :to="{ path: `estimates/${row.data.id}/view` }" |               :to="{ path: `estimates/${row.data.id}/view` }" | ||||||
|               class="font-medium text-primary-500 dark:text-primary-400" |               class="font-medium text-primary-500" | ||||||
|             > |             > | ||||||
|               {{ row.data.customer.name }} |               {{ row.data.customer.name }} | ||||||
|             </router-link> |             </router-link> | ||||||
|  | |||||||
| @ -164,7 +164,7 @@ | |||||||
|           </template> |           </template> | ||||||
|  |  | ||||||
|           <BaseDropdownItem @click="removeMultipleEstimates"> |           <BaseDropdownItem @click="removeMultipleEstimates"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -205,7 +205,7 @@ | |||||||
|         <template #cell-estimate_number="{ row }"> |         <template #cell-estimate_number="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `estimates/${row.data.id}/view` }" |             :to="{ path: `estimates/${row.data.id}/view` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.estimate_number }} |             {{ row.data.estimate_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -135,7 +135,7 @@ | |||||||
|             v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)" |             v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)" | ||||||
|             @click="removeMultipleExpenses" |             @click="removeMultipleExpenses" | ||||||
|           > |           > | ||||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -171,7 +171,7 @@ | |||||||
|         <template #cell-name="{ row }"> |         <template #cell-name="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `expenses/${row.data.id}/edit` }" |             :to="{ path: `expenses/${row.data.id}/edit` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.expense_category.name }} |             {{ row.data.expense_category.name }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="flex flex-col items-center justify-between w-full pt-10"> |   <div class="flex flex-col items-center justify-between w-full pt-10"> | ||||||
|     <LightDarkButton class="absolute z-10 top-2 right-2"/> |  | ||||||
|     <img |     <img | ||||||
|       id="logo-crater" |       id="logo-crater" | ||||||
|       src="/img/crater-logo.png" |       src="/img/crater-logo.png" | ||||||
| @ -30,7 +29,6 @@ import Step7CompanyInfo from './Step7CompanyInfo.vue' | |||||||
| import Step8CompanyPreferences from './Step8CompanyPreferences.vue' | import Step8CompanyPreferences from './Step8CompanyPreferences.vue' | ||||||
| import { useInstallationStore } from '@/scripts/admin/stores/installation' | import { useInstallationStore } from '@/scripts/admin/stores/installation' | ||||||
| import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||||
| import LightDarkButton from '@/scripts/components/LightDarkButton.vue' |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   components: { |   components: { | ||||||
| @ -42,7 +40,6 @@ export default { | |||||||
|     step_6: Step6AccountSettings, |     step_6: Step6AccountSettings, | ||||||
|     step_7: Step7CompanyInfo, |     step_7: Step7CompanyInfo, | ||||||
|     step_8: Step8CompanyPreferences, |     step_8: Step8CompanyPreferences, | ||||||
|     LightDarkButton |  | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   setup() { |   setup() { | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|       <div class="mb-6"> |       <div class="mb-6"> | ||||||
|         <div |         <div | ||||||
|           v-if="phpSupportInfo" |           v-if="phpSupportInfo" | ||||||
|           class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 lg:gap-24 sm:gap-4 dark:border-white/10" |           class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200  lg:gap-24 sm:gap-4" | ||||||
|         > |         > | ||||||
|           <div class="col-span-2 text-sm"> |           <div class="col-span-2 text-sm"> | ||||||
|             {{ |             {{ | ||||||
| @ -32,7 +32,7 @@ | |||||||
|           <div |           <div | ||||||
|             v-for="(requirement, index) in requirements" |             v-for="(requirement, index) in requirements" | ||||||
|             :key="index" |             :key="index" | ||||||
|             class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 dark:border-gray-600 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" | ||||||
|           > |           > | ||||||
|             <div class="col-span-2 text-sm"> |             <div class="col-span-2 text-sm"> | ||||||
|               {{ index }} |               {{ index }} | ||||||
|  | |||||||
| @ -8,7 +8,12 @@ | |||||||
|       <div |       <div | ||||||
|         v-for="(permission, index) in 3" |         v-for="(permission, index) in 3" | ||||||
|         :key="index" |         :key="index" | ||||||
|         class="grid grid-flow-row grid-cols-3 border border-gray-200 lg:gap-24 sm:gap-4 dark:border-gray-600" |         class=" | ||||||
|  |           grid grid-flow-row grid-cols-3 | ||||||
|  |           lg:gap-24 | ||||||
|  |           sm:gap-4 | ||||||
|  |           border border-gray-200 | ||||||
|  |         " | ||||||
|       > |       > | ||||||
|         <BaseContentPlaceholdersText :lines="1" class="col-span-4 p-3" /> |         <BaseContentPlaceholdersText :lines="1" class="col-span-4 p-3" /> | ||||||
|       </div> |       </div> | ||||||
| @ -24,7 +29,7 @@ | |||||||
|       <div |       <div | ||||||
|         v-for="(permission, index) in permissions" |         v-for="(permission, index) in permissions" | ||||||
|         :key="index" |         :key="index" | ||||||
|         class="border border-gray-200 dark:border-gray-600" |         class="border border-gray-200" | ||||||
|       > |       > | ||||||
|         <div class="grid grid-flow-row grid-cols-3 lg:gap-24 sm:gap-4"> |         <div class="grid grid-flow-row grid-cols-3 lg:gap-24 sm:gap-4"> | ||||||
|           <div class="col-span-2 p-3"> |           <div class="col-span-2 p-3"> | ||||||
| @ -33,11 +38,11 @@ | |||||||
|           <div class="p-3 text-right"> |           <div class="p-3 text-right"> | ||||||
|             <span |             <span | ||||||
|               v-if="permission.isSet" |               v-if="permission.isSet" | ||||||
|               class="inline-block w-4 h-4 ml-3 mr-2 bg-green-500 rounded-full" |               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-green-500" | ||||||
|             /> |             /> | ||||||
|             <span |             <span | ||||||
|               v-else |               v-else | ||||||
|               class="inline-block w-4 h-4 ml-3 mr-2 bg-red-500 rounded-full" |               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-red-500" | ||||||
|             /> |             /> | ||||||
|             <span>{{ permission.permission }}</span> |             <span>{{ permission.permission }}</span> | ||||||
|           </div> |           </div> | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
|   <BaseWizardStep |   <BaseWizardStep | ||||||
|     :title="$t('wizard.database.database')" |     :title="$t('wizard.database.database')" | ||||||
|     :description="$t('wizard.database.desc')" |     :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 |     <component | ||||||
|       :is="databaseData.database_connection" |       :is="databaseData.database_connection" | ||||||
|  | |||||||
| @ -18,18 +18,18 @@ | |||||||
|       </BaseInputGroup> |       </BaseInputGroup> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <p class="mt-4 mb-0 text-sm text-gray-600 dark:text-white">Notes:</p> |     <p class="mt-4 mb-0 text-sm text-gray-600">Notes:</p> | ||||||
|     <ul class="w-full text-gray-600 list-disc list-inside dark:text-gray-300"> |     <ul class="w-full text-gray-600 list-disc list-inside"> | ||||||
|       <li class="text-sm leading-8"> |       <li class="text-sm leading-8"> | ||||||
|         App domain should not contain |         App domain should not contain | ||||||
|         <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-sm">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 |         <b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> in front of | ||||||
|         the domain. |         the domain. | ||||||
|       </li> |       </li> | ||||||
|       <li class="text-sm leading-8"> |       <li class="text-sm leading-8"> | ||||||
|         If you're accessing the website on a different port, please mention the |         If you're accessing the website on a different port, please mention the | ||||||
|         port. For example: |         port. For example: | ||||||
|         <b class="inline-block px-1 bg-gray-100 rounded-md dark:bg-gray-400 dark:text-gray-600">localhost:8080</b> |         <b class="inline-block px-1 bg-gray-100">localhost:8080</b> | ||||||
|       </li> |       </li> | ||||||
|     </ul> |     </ul> | ||||||
|  |  | ||||||
|  | |||||||
| @ -68,15 +68,13 @@ | |||||||
|             @input="v$.userForm.password.$touch()" |             @input="v$.userForm.password.$touch()" | ||||||
|           > |           > | ||||||
|             <template #right> |             <template #right> | ||||||
|               <BaseIcon |               <EyeOffIcon | ||||||
|                 v-if="isShowPassword" |                 v-if="isShowPassword" | ||||||
|                 name="EyeOffIcon" |  | ||||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" |                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||||
|                 @click="isShowPassword = !isShowPassword" |                 @click="isShowPassword = !isShowPassword" | ||||||
|               /> |               /> | ||||||
|               <BaseIcon |               <EyeIcon | ||||||
|                 v-else |                 v-else | ||||||
|                 name="EyeIcon" |  | ||||||
|                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" |                 class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||||
|                 @click="isShowPassword = !isShowPassword" |                 @click="isShowPassword = !isShowPassword" | ||||||
|               /> |               /> | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
|   <BaseWizardStep |   <BaseWizardStep | ||||||
|     :title="$t('wizard.company_info')" |     :title="$t('wizard.company_info')" | ||||||
|     :description="$t('wizard.company_info_desc')" |     :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"> |     <form action="" @submit.prevent="next"> | ||||||
|       <div class="grid grid-cols-1 mb-4 md:grid-cols-2 md:mb-6"> |       <div class="grid grid-cols-1 mb-4 md:grid-cols-2 md:mb-6"> | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
|   <BaseWizardStep |   <BaseWizardStep | ||||||
|     :title="$t('wizard.preferences')" |     :title="$t('wizard.preferences')" | ||||||
|     :description="$t('wizard.preferences_desc')" |     :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"> |     <form action="" @submit.prevent="next"> | ||||||
|       <div> |       <div> | ||||||
|  | |||||||
| @ -178,7 +178,7 @@ | |||||||
|           </template> |           </template> | ||||||
|  |  | ||||||
|           <BaseDropdownItem @click="removeMultipleInvoices"> |           <BaseDropdownItem @click="removeMultipleInvoices"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -220,7 +220,7 @@ | |||||||
|         <template #cell-invoice_number="{ row }"> |         <template #cell-invoice_number="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `invoices/${row.data.id}/view` }" |             :to="{ path: `invoices/${row.data.id}/view` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.invoice_number }} |             {{ row.data.invoice_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -117,7 +117,7 @@ | |||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|           <BaseDropdownItem @click="removeMultipleItems"> |           <BaseDropdownItem @click="removeMultipleItems"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -153,7 +153,7 @@ | |||||||
|         <template #cell-name="{ row }"> |         <template #cell-name="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `items/${row.data.id}/edit` }" |             :to="{ path: `items/${row.data.id}/edit` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.name }} |             {{ row.data.name }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -116,7 +116,7 @@ | |||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|           <BaseDropdownItem @click="removeMultiplePayments"> |           <BaseDropdownItem @click="removeMultiplePayments"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -158,7 +158,7 @@ | |||||||
|         <template #cell-payment_number="{ row }"> |         <template #cell-payment_number="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `payments/${row.data.id}/view` }" |             :to="{ path: `payments/${row.data.id}/view` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.payment_number }} |             {{ row.data.payment_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -151,12 +151,12 @@ | |||||||
|               " |               " | ||||||
|             > |             > | ||||||
|               {{ $t('general.actions') }} |               {{ $t('general.actions') }} | ||||||
|               <BaseIcon name="ChevronDownIcon"/> |               <BaseIcon name="ChevronDownIcon" class="h-5" /> | ||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|  |  | ||||||
|           <BaseDropdownItem @click="removeMultipleRecurringInvoices()"> |           <BaseDropdownItem @click="removeMultipleRecurringInvoices()"> | ||||||
|             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -204,7 +204,7 @@ | |||||||
|               :text="row.data.customer.name" |               :text="row.data.customer.name" | ||||||
|               :length="30" |               :length="30" | ||||||
|               tag="span" |               tag="span" | ||||||
|               class="font-medium text-primary-500 flex flex-col dark:text-primary-400" |               class="font-medium text-primary-500 flex flex-col" | ||||||
|             /> |             /> | ||||||
|  |  | ||||||
|             <BaseText |             <BaseText | ||||||
|  | |||||||
| @ -92,7 +92,7 @@ | |||||||
|           <tr |           <tr | ||||||
|             v-for="(ext, i) in requiredExtentions" |             v-for="(ext, i) in requiredExtentions" | ||||||
|             :key="i" |             :key="i" | ||||||
|             class="p-2 border-2 border-gray-200 dark:border-gray-600" |             class="p-2 border-2 border-gray-200" | ||||||
|           > |           > | ||||||
|             <td width="70%" class="p-2 text-sm truncate"> |             <td width="70%" class="p-2 text-sm truncate"> | ||||||
|               {{ i }} |               {{ i }} | ||||||
| @ -121,7 +121,7 @@ | |||||||
|             {{ $t('settings.update_app.update_progress') }} |             {{ $t('settings.update_app.update_progress') }} | ||||||
|           </h6> |           </h6> | ||||||
|           <p |           <p | ||||||
|             class="mb-8 text-sm leading-snug text-gray-500 dark:text-gray-400" |             class="mb-8 text-sm leading-snug text-gray-500" | ||||||
|             style="max-width: 480px" |             style="max-width: 480px" | ||||||
|           > |           > | ||||||
|             {{ $t('settings.update_app.progress_text') }} |             {{ $t('settings.update_app.progress_text') }} | ||||||
| @ -135,11 +135,11 @@ | |||||||
|         <li |         <li | ||||||
|           v-for="step in updateSteps" |           v-for="step in updateSteps" | ||||||
|           :key="step.stepUrl" |           :key="step.stepUrl" | ||||||
|           class="flex justify-between w-full py-3 border-b border-gray-200 dark:border-gray-600 border-solid last:border-b-0" |           class="flex justify-between w-full py-3 border-b border-gray-200 border-solid last:border-b-0" | ||||||
|         > |         > | ||||||
|           <p class="m-0 text-sm dark:text-gray-300 leading-8">{{ $t(step.translationKey) }}</p> |           <p class="m-0 text-sm leading-8">{{ $t(step.translationKey) }}</p> | ||||||
|           <div class="flex flex-row items-center"> |           <div class="flex flex-row items-center"> | ||||||
|             <span v-if="step.time" class="mr-3 text-xs text-gray-500 dark:text-gray-300"> |             <span v-if="step.time" class="mr-3 text-xs text-gray-500"> | ||||||
|               {{ step.time }} |               {{ step.time }} | ||||||
|             </span> |             </span> | ||||||
|             <span |             <span | ||||||
| @ -275,7 +275,7 @@ function statusClass(step) { | |||||||
|     case 'running': |     case 'running': | ||||||
|       return 'text-blue-400 bg-blue-100' |       return 'text-blue-400 bg-blue-100' | ||||||
|     case 'error': |     case 'error': | ||||||
|       return 'text-red-400 bg-red-200' |       return 'text-danger bg-red-200' | ||||||
|     default: |     default: | ||||||
|       return '' |       return '' | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -51,12 +51,27 @@ | |||||||
|         <BaseInput |         <BaseInput | ||||||
|           v-model.trim="mailDriverStore.mailgunConfig.mail_mailgun_secret" |           v-model.trim="mailDriverStore.mailgunConfig.mail_mailgun_secret" | ||||||
|           :content-loading="isFetchingInitialData" |           :content-loading="isFetchingInitialData" | ||||||
|           type="password" |           :type="getInputType" | ||||||
|           name="mailgun_secret" |           name="mailgun_secret" | ||||||
|           autocomplete="off" |           autocomplete="off" | ||||||
|           :invalid="v$.mailgunConfig.mail_mailgun_secret.$error" |           :invalid="v$.mailgunConfig.mail_mailgun_secret.$error" | ||||||
|           @input="v$.mailgunConfig.mail_mailgun_secret.$touch()" |           @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> | ||||||
|  |  | ||||||
|       <BaseInputGroup |       <BaseInputGroup | ||||||
| @ -169,6 +184,15 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | |||||||
| const mailDriverStore = useMailDriverStore() | const mailDriverStore = useMailDriverStore() | ||||||
| const { t } = useI18n() | const { t } = useI18n() | ||||||
|  |  | ||||||
|  | let isShowPassword = ref(false) | ||||||
|  |  | ||||||
|  | const getInputType = computed(() => { | ||||||
|  |   if (isShowPassword.value) { | ||||||
|  |     return 'text' | ||||||
|  |   } | ||||||
|  |   return 'password' | ||||||
|  | }) | ||||||
|  |  | ||||||
| const rules = computed(() => { | const rules = computed(() => { | ||||||
|   return { |   return { | ||||||
|     mailgunConfig: { |     mailgunConfig: { | ||||||
|  | |||||||
| @ -146,12 +146,27 @@ | |||||||
|         <BaseInput |         <BaseInput | ||||||
|           v-model.trim="mailDriverStore.sesConfig.mail_ses_secret" |           v-model.trim="mailDriverStore.sesConfig.mail_ses_secret" | ||||||
|           :content-loading="isFetchingInitialData" |           :content-loading="isFetchingInitialData" | ||||||
|           type="password" |           :type="getInputType" | ||||||
|           name="mail_ses_secret" |           name="mail_ses_secret" | ||||||
|           autocomplete="off" |           autocomplete="off" | ||||||
|           :invalid="v$.sesConfig.mail_ses_secret.$error" |           :invalid="v$.sesConfig.mail_ses_secret.$error" | ||||||
|           @input="v$.sesConfig.mail_ses_secret.$touch()" |           @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> |       </BaseInputGroup> | ||||||
|     </BaseInputGrid> |     </BaseInputGrid> | ||||||
|  |  | ||||||
| @ -208,6 +223,7 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | |||||||
| const mailDriverStore = useMailDriverStore() | const mailDriverStore = useMailDriverStore() | ||||||
| const { t } = useI18n() | const { t } = useI18n() | ||||||
|  |  | ||||||
|  | let isShowPassword = ref(false) | ||||||
| const encryptions = reactive(['tls', 'ssl', 'starttls']) | const encryptions = reactive(['tls', 'ssl', 'starttls']) | ||||||
|  |  | ||||||
| const rules = computed(() => { | const rules = computed(() => { | ||||||
| @ -248,6 +264,13 @@ const v$ = useVuelidate( | |||||||
|   computed(() => mailDriverStore) |   computed(() => mailDriverStore) | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | const getInputType = computed(() => { | ||||||
|  |   if (isShowPassword.value) { | ||||||
|  |     return 'text' | ||||||
|  |   } | ||||||
|  |   return 'password' | ||||||
|  | }) | ||||||
|  |  | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   for (const key in mailDriverStore.sesConfig) { |   for (const key in mailDriverStore.sesConfig) { | ||||||
|     if (props.configData.hasOwnProperty(key)) { |     if (props.configData.hasOwnProperty(key)) { | ||||||
|  | |||||||
| @ -58,9 +58,24 @@ | |||||||
|         <BaseInput |         <BaseInput | ||||||
|           v-model.trim="mailDriverStore.smtpConfig.mail_password" |           v-model.trim="mailDriverStore.smtpConfig.mail_password" | ||||||
|           :content-loading="isFetchingInitialData" |           :content-loading="isFetchingInitialData" | ||||||
|           type="password" |           :type="getInputType" | ||||||
|           name="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> | ||||||
|  |  | ||||||
|       <BaseInputGroup |       <BaseInputGroup | ||||||
| @ -194,8 +209,17 @@ const emit = defineEmits(['submit-data', 'on-change-driver']) | |||||||
|  |  | ||||||
| const mailDriverStore = useMailDriverStore() | const mailDriverStore = useMailDriverStore() | ||||||
| const { t } = useI18n() | const { t } = useI18n() | ||||||
|  |  | ||||||
|  | let isShowPassword = ref(false) | ||||||
| const encryptions = reactive(['tls', 'ssl', 'starttls']) | const encryptions = reactive(['tls', 'ssl', 'starttls']) | ||||||
|  |  | ||||||
|  | const getInputType = computed(() => { | ||||||
|  |   if (isShowPassword.value) { | ||||||
|  |     return 'text' | ||||||
|  |   } | ||||||
|  |   return 'password' | ||||||
|  | }) | ||||||
|  |  | ||||||
| const rules = computed(() => { | const rules = computed(() => { | ||||||
|   return { |   return { | ||||||
|     smtpConfig: { |     smtpConfig: { | ||||||
|  | |||||||
| @ -118,11 +118,11 @@ | |||||||
|               " |               " | ||||||
|             > |             > | ||||||
|               {{ $t('general.actions') }} |               {{ $t('general.actions') }} | ||||||
|               <BaseIcon name="ChevronDownIcon"/> |               <BaseIcon name="ChevronDownIcon" class="h-5" /> | ||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|           <BaseDropdownItem @click="removeMultipleUsers"> |           <BaseDropdownItem @click="removeMultipleUsers"> | ||||||
|             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600 dark:text-gray-400 dark:group-hover:text-white" /> |             <BaseIcon name="TrashIcon" class="h-5 mr-3 text-gray-600" /> | ||||||
|             {{ $t('general.delete') }} |             {{ $t('general.delete') }} | ||||||
|           </BaseDropdownItem> |           </BaseDropdownItem> | ||||||
|         </BaseDropdown> |         </BaseDropdown> | ||||||
| @ -158,7 +158,7 @@ | |||||||
|         <template #cell-name="{ row }"> |         <template #cell-name="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `users/${row.data.id}/edit` }" |             :to="{ path: `users/${row.data.id}/edit` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.name }} |             {{ row.data.name }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ | |||||||
|     " |     " | ||||||
|     @click="onChange" |     @click="onChange" | ||||||
|   > |   > | ||||||
|   <BaseIcon v-if="!globalStore.isDarkModeOn" class="h-5 w-5 text-yellow-500" name="SunIcon" /> |     <BaseIcon v-if="!globalStore.isDarkModeOn" class="h-5 w-5 text-black" name="SunIcon" /> | ||||||
|     <BaseIcon v-else class="h-5 w-5 text-white" name="MoonIcon" /> |     <BaseIcon v-else class="h-5 w-5 text-white" name="MoonIcon" /> | ||||||
|   </button> |   </button> | ||||||
| </template> | </template> | ||||||
| @ -24,6 +24,14 @@ import { useGlobalStore } from '@/scripts/customer/stores/global' | |||||||
| 
 | 
 | ||||||
| const globalStore = useGlobalStore() | const globalStore = useGlobalStore() | ||||||
| 
 | 
 | ||||||
|  | const enabled = computed( | ||||||
|  |   ()=> | ||||||
|  |     localStorage.getItem('theme') === 'dark' || | ||||||
|  |     document.documentElement.classList.contains('dark') | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | globalStore.isDarkModeOn = enabled.value | ||||||
|  | 
 | ||||||
| function onChange() { | function onChange() { | ||||||
|   globalStore.isDarkModeOn = !globalStore.isDarkModeOn |   globalStore.isDarkModeOn = !globalStore.isDarkModeOn | ||||||
| 
 | 
 | ||||||
| @ -35,6 +43,7 @@ function onChange() { | |||||||
|     localStorage.theme = 'light' |     localStorage.theme = 'light' | ||||||
|     document.documentElement.classList.remove('dark') |     document.documentElement.classList.remove('dark') | ||||||
|     document.documentElement.style.setProperty('color-scheme', 'light') |     document.documentElement.style.setProperty('color-scheme', 'light') | ||||||
|  | 
 | ||||||
|   } |   } | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| @ -93,7 +93,6 @@ | |||||||
|                     rounded-full |                     rounded-full | ||||||
|                     text-primary-500 |                     text-primary-500 | ||||||
|                     dark:bg-gray-600 |                     dark:bg-gray-600 | ||||||
|                     dark:text-primary-400 |  | ||||||
|                   " |                   " | ||||||
|                 > |                 > | ||||||
|                   {{ initGenerator(customer.name) }} |                   {{ initGenerator(customer.name) }} | ||||||
| @ -142,7 +141,6 @@ | |||||||
|                     bg-gray-200 |                     bg-gray-200 | ||||||
|                     rounded-full |                     rounded-full | ||||||
|                     text-primary-500 |                     text-primary-500 | ||||||
|                     dark:text-primary-400 |  | ||||||
|                     dark:bg-gray-600 |                     dark:bg-gray-600 | ||||||
|                   " |                   " | ||||||
|                 > |                 > | ||||||
|  | |||||||
| @ -16,28 +16,26 @@ defineProps({ | |||||||
|  |  | ||||||
| const globalStore = useGlobalStore() | const globalStore = useGlobalStore() | ||||||
|  |  | ||||||
| const isDark = ref( | const enabled = ref( | ||||||
|   localStorage.getItem('theme') === 'dark' |   localStorage.getItem('theme') === 'dark' || | ||||||
|     || document.documentElement.classList.contains('dark'), |     document.documentElement.classList.contains('dark') | ||||||
| ) | ) | ||||||
|  |  | ||||||
| globalStore.isDarkModeOn = isDark | globalStore.isDarkModeOn = enabled | ||||||
|  |  | ||||||
| const enabled = computed({ | function onChange(val) { | ||||||
|   get: () => globalStore.isDarkModeOn, |   if (val) { | ||||||
|   set: (value) => { |     localStorage.theme = 'dark' | ||||||
|     if (value) { |     document.documentElement.classList.add('dark') | ||||||
|       localStorage.theme = 'dark' |     document.documentElement.style.setProperty('color-scheme', 'dark') | ||||||
|       document.documentElement.classList.add('dark') |     globalStore.isDarkModeOn = true | ||||||
|       document.documentElement.style.setProperty('color-scheme', 'dark') |   } else { | ||||||
|     } else { |     localStorage.theme = 'light' | ||||||
|       localStorage.theme = 'light' |     document.documentElement.classList.remove('dark') | ||||||
|       document.documentElement.classList.remove('dark') |     document.documentElement.style.setProperty('color-scheme', 'light') | ||||||
|       document.documentElement.style.setProperty('color-scheme', 'light') |     globalStore.isDarkModeOn = false | ||||||
|     } |   } | ||||||
|     globalStore.isDarkModeOn = value | } | ||||||
|   }, |  | ||||||
| }) |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
| @ -51,6 +49,7 @@ const enabled = computed({ | |||||||
|         v-model="enabled" |         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="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']" |         :class="[enabled ? 'bg-primary-600' : 'bg-gray-200']" | ||||||
|  |         @update:modelValue="onChange" | ||||||
|       > |       > | ||||||
|         <span class="sr-only">Use setting</span> |         <span class="sr-only">Use setting</span> | ||||||
|         <span |         <span | ||||||
|  | |||||||
| @ -90,7 +90,7 @@ | |||||||
|  |  | ||||||
|     <input |     <input | ||||||
|       v-bind="$attrs" |       v-bind="$attrs" | ||||||
|       :type="getType" |       :type="type" | ||||||
|       :value="modelValue" |       :value="modelValue" | ||||||
|       :disabled="disabled" |       :disabled="disabled" | ||||||
|       :class="[ |       :class="[ | ||||||
| @ -144,44 +144,6 @@ | |||||||
|     > |     > | ||||||
|       <slot name="right" :class="iconRightClass" /> |       <slot name="right" :class="iconRightClass" /> | ||||||
|     </div> |     </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> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @ -257,15 +219,6 @@ const slots = useSlots() | |||||||
|  |  | ||||||
| const emit = defineEmits(['update:modelValue']) | 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(() => { | const hasLeftIconSlot = computed(() => { | ||||||
|   return !!slots.left || (props.loading && props.loadingPosition === 'left') |   return !!slots.left || (props.loading && props.loadingPosition === 'left') | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -1,7 +1,16 @@ | |||||||
| <template> | <template> | ||||||
|   <div |   <div | ||||||
|     :class="containerClass" |     :class="containerClass" | ||||||
|     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" |     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 | ||||||
|  |     " | ||||||
|   > |   > | ||||||
|     <a |     <a | ||||||
|       v-for="(number, index) in steps" |       v-for="(number, index) in steps" | ||||||
| @ -49,21 +58,21 @@ export default { | |||||||
|     }, |     }, | ||||||
|     currentStepClass: { |     currentStepClass: { | ||||||
|       type: String, |       type: String, | ||||||
|       default: 'bg-white border-primary-500 dark:bg-gray-600 dark:border-gray-500 dark:border-primary-600', |       default: 'bg-white border-primary-500', | ||||||
|     }, |     }, | ||||||
|     nextStepClass: { |     nextStepClass: { | ||||||
|       type: String, |       type: String, | ||||||
|       default: 'border-gray-200 bg-white dark:bg-gray-600 dark:border-gray-500', |       default: 'border-gray-200 bg-white', | ||||||
|     }, |     }, | ||||||
|     previousStepClass: { |     previousStepClass: { | ||||||
|       type: String, |       type: String, | ||||||
|       default: |       default: | ||||||
|         'bg-primary-500 dark:bg-primary-600 border-primary-500 flex justify-center items-center dark:border-primary-600', |         'bg-primary-500 border-primary-500 flex justify-center items-center', | ||||||
|     }, |     }, | ||||||
|     iconClass: { |     iconClass: { | ||||||
|       type: String, |       type: String, | ||||||
|       default: |       default: | ||||||
|         'flex items-center justify-center w-full h-full text-sm font-black text-center text-white dark:text-gray-400', |         'flex items-center justify-center w-full h-full text-sm font-black text-center text-white', | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|  | |||||||
| @ -9,7 +9,6 @@ | |||||||
|       </p> |       </p> | ||||||
|     </div> |     </div> | ||||||
|     <slot /> |     <slot /> | ||||||
|     <BaseDarkHighlight class="z-[-1]"/> |  | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @ -26,16 +25,16 @@ const props = defineProps({ | |||||||
|   stepContainerClass: { |   stepContainerClass: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: |     default: | ||||||
|       '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', |       'w-full p-8 mb-8 bg-white border border-gray-200 border-solid rounded', | ||||||
|   }, |   }, | ||||||
|   stepTitleClass: { |   stepTitleClass: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: 'text-2xl not-italic font-semibold leading-7 text-black dark:text-white', |     default: 'text-2xl not-italic font-semibold leading-7 text-black', | ||||||
|   }, |   }, | ||||||
|   stepDescriptionClass: { |   stepDescriptionClass: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: |     default: | ||||||
|       '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', |       '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', | ||||||
|   }, |   }, | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ | |||||||
|         </div> |         </div> | ||||||
|         <div class="hidden sm:ml-6 sm:flex sm:items-center"> |         <div class="hidden sm:ml-6 sm:flex sm:items-center"> | ||||||
|           <!-- Dark mode Toggle --> |           <!-- Dark mode Toggle --> | ||||||
|           <LightDarkButton/> |           <CustomerLightDarkButton/> | ||||||
|  |  | ||||||
|           <!-- Profile dropdown --> |           <!-- Profile dropdown --> | ||||||
|  |  | ||||||
| @ -151,7 +151,7 @@ | |||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|           <!-- Dark mode Toggle --> |           <!-- Dark mode Toggle --> | ||||||
|           <LightDarkButton/> |           <CustomerLightDarkButton/> | ||||||
|         </div> |         </div> | ||||||
|         <div class="mt-3 space-y-1"> |         <div class="mt-3 space-y-1"> | ||||||
|           <router-link |           <router-link | ||||||
| @ -178,7 +178,7 @@ import { useRoute, useRouter } from 'vue-router' | |||||||
| import { ref, watch, computed } from 'vue' | import { ref, watch, computed } from 'vue' | ||||||
| import { useGlobalStore } from '@/scripts/customer/stores/global' | import { useGlobalStore } from '@/scripts/customer/stores/global' | ||||||
| import MainLogo from '@/scripts/components/icons/MainLogo.vue' | import MainLogo from '@/scripts/components/icons/MainLogo.vue' | ||||||
| import LightDarkButton from '@/scripts/components/LightDarkButton.vue' | import CustomerLightDarkButton from '@/scripts/components/CustomerLightDarkButton.vue' | ||||||
| import { | import { | ||||||
|   Disclosure, |   Disclosure, | ||||||
|   DisclosureButton, |   DisclosureButton, | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ export const useGlobalStore = defineStore({ | |||||||
|     companySlug: '', |     companySlug: '', | ||||||
|     mainMenu: null, |     mainMenu: null, | ||||||
|     enabledModules: [], |     enabledModules: [], | ||||||
|     isDarkModeOn: localStorage.getItem('theme') === 'dark' || document.documentElement.classList.contains('dark') |     isDarkModeOn: false | ||||||
|   }), |   }), | ||||||
|  |  | ||||||
|   actions: { |   actions: { | ||||||
|  | |||||||
| @ -32,10 +32,25 @@ | |||||||
|     > |     > | ||||||
|       <BaseInput |       <BaseInput | ||||||
|         v-model="authStore.loginData.password" |         v-model="authStore.loginData.password" | ||||||
|  |         :type="getInputType" | ||||||
|         :invalid="v$.loginData.password.$error" |         :invalid="v$.loginData.password.$error" | ||||||
|         type="password" |  | ||||||
|         @input="v$.loginData.password.$touch()" |         @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> |     </BaseInputGroup> | ||||||
|     <div class="flex items-center justify-between"> |     <div class="flex items-center justify-between"> | ||||||
|       <router-link |       <router-link | ||||||
| @ -76,6 +91,14 @@ const authStore = useAuthStore() | |||||||
| const { t } = useI18n() | const { t } = useI18n() | ||||||
|  |  | ||||||
| let isLoading = ref(false) | let isLoading = ref(false) | ||||||
|  | const isShowPassword = ref(false) | ||||||
|  |  | ||||||
|  | const getInputType = computed(() => { | ||||||
|  |   if (isShowPassword.value) { | ||||||
|  |     return 'text' | ||||||
|  |   } | ||||||
|  |   return 'password' | ||||||
|  | }) | ||||||
|  |  | ||||||
| const rules = computed(() => { | const rules = computed(() => { | ||||||
|   return { |   return { | ||||||
|  | |||||||
| @ -23,11 +23,23 @@ | |||||||
|     > |     > | ||||||
|       <BaseInput |       <BaseInput | ||||||
|         v-model="loginData.password" |         v-model="loginData.password" | ||||||
|         type="password" |         :type="isShowPassword ? 'text' : 'password'" | ||||||
|         name="password" |         name="password" | ||||||
|         :invalid="v$.password.$error" |         :invalid="v$.password.$error" | ||||||
|         @input="v$.password.$touch()" |         @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> | ||||||
|  |  | ||||||
|     <BaseInputGroup |     <BaseInputGroup | ||||||
| @ -81,6 +93,7 @@ const loginData = reactive({ | |||||||
|  |  | ||||||
| const globalStore = useGlobalStore() | const globalStore = useGlobalStore() | ||||||
|  |  | ||||||
|  | let isShowPassword = ref(false) | ||||||
| let isLoading = ref(false) | let isLoading = ref(false) | ||||||
|  |  | ||||||
| const rules = computed(() => { | const rules = computed(() => { | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ | |||||||
|             :to="{ |             :to="{ | ||||||
|               path: `/${globalStore.companySlug}/customer/invoices/${row.data.id}/view`, |               path: `/${globalStore.companySlug}/customer/invoices/${row.data.id}/view`, | ||||||
|             }" |             }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.invoice_number }} |             {{ row.data.invoice_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
| @ -73,7 +73,7 @@ | |||||||
|             :to="{ |             :to="{ | ||||||
|               path: `/${globalStore.companySlug}/customer/estimates/${row.data.id}/view`, |               path: `/${globalStore.companySlug}/customer/estimates/${row.data.id}/view`, | ||||||
|             }" |             }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.estimate_number }} |             {{ row.data.estimate_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -100,7 +100,7 @@ | |||||||
|         <template #cell-estimate_number="{ row }"> |         <template #cell-estimate_number="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `estimates/${row.data.id}/view` }" |             :to="{ path: `estimates/${row.data.id}/view` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.estimate_number }} |             {{ row.data.estimate_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -95,7 +95,7 @@ | |||||||
|         <template #cell-invoice_number="{ row }"> |         <template #cell-invoice_number="{ row }"> | ||||||
|           <router-link |           <router-link | ||||||
|             :to="{ path: `invoices/${row.data.id}/view` }" |             :to="{ path: `invoices/${row.data.id}/view` }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.invoice_number }} |             {{ row.data.invoice_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -78,7 +78,7 @@ | |||||||
|             :to="{ |             :to="{ | ||||||
|               path: `payments/${row.data.id}/view`, |               path: `payments/${row.data.id}/view`, | ||||||
|             }" |             }" | ||||||
|             class="font-medium text-primary-500 dark:text-primary-400" |             class="font-medium text-primary-500" | ||||||
|           > |           > | ||||||
|             {{ row.data.payment_number }} |             {{ row.data.payment_number }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | |||||||
| @ -66,10 +66,24 @@ | |||||||
|         > |         > | ||||||
|           <BaseInput |           <BaseInput | ||||||
|             v-model="userStore.userForm.password" |             v-model="userStore.userForm.password" | ||||||
|             type="password" |             :type="isShowPassword ? 'text' : 'password'" | ||||||
|             :invalid="v$.userForm.password.$error" |             :invalid="v$.userForm.password.$error" | ||||||
|             @input="v$.userForm.password.$touch()" |             @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> | ||||||
|  |  | ||||||
|         <BaseInputGroup |         <BaseInputGroup | ||||||
| @ -81,10 +95,24 @@ | |||||||
|         > |         > | ||||||
|           <BaseInput |           <BaseInput | ||||||
|             v-model="userStore.userForm.confirm_password" |             v-model="userStore.userForm.confirm_password" | ||||||
|             type="password" |             :type="isShowConfirmPassword ? 'text' : 'password'" | ||||||
|             :invalid="v$.userForm.confirm_password.$error" |             :invalid="v$.userForm.confirm_password.$error" | ||||||
|             @input="v$.userForm.confirm_password.$touch()" |             @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> |         </BaseInputGroup> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
| @ -123,6 +151,8 @@ const { t, tm } = useI18n() | |||||||
| let imgFiles = ref([]) | let imgFiles = ref([]) | ||||||
| let isSaving = ref(false) | let isSaving = ref(false) | ||||||
| let avatarFileBlob = ref(null) | let avatarFileBlob = ref(null) | ||||||
|  | let isShowPassword = ref(false) | ||||||
|  | let isShowConfirmPassword = ref(false) | ||||||
| const isCustomerAvatarRemoved = ref(false) | const isCustomerAvatarRemoved = ref(false) | ||||||
|  |  | ||||||
| if (userStore.userForm.avatar) { | if (userStore.userForm.avatar) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	