mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-31 13:41:09 -04:00 
			
		
		
		
	* fix sidebar and table data link in dark mode color * add dark mode toggle in installation step
		
			
				
	
	
		
			247 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <Disclosure
 | |
|     v-slot="{ open }"
 | |
|     as="nav"
 | |
|     class="bg-white shadow-sm fixed top-0 left-0 z-20 w-full dark:bg-gray-800"
 | |
|   >
 | |
|     <BaseDarkHighlight />
 | |
|     <div class="mx-auto px-8">
 | |
|       <div class="flex justify-between h-16 w-full">
 | |
|         <div class="flex">
 | |
|           <div class="shrink-0 flex items-center">
 | |
|             <a
 | |
|               :href="`/${globalStore.companySlug}/customer/dashboard`"
 | |
|               class="
 | |
|                 float-none
 | |
|                 text-lg
 | |
|                 not-italic
 | |
|                 font-black
 | |
|                 tracking-wider
 | |
|                 text-white
 | |
|                 brand-main
 | |
|                 md:float-left
 | |
|                 font-base
 | |
|               "
 | |
|             >
 | |
|               <MainLogo v-if="!customerLogo" class="h-6" />
 | |
|               <img v-else :src="customerLogo" class="h-6" />
 | |
|             </a>
 | |
|           </div>
 | |
|           <div class="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
 | |
|             <router-link
 | |
|               v-for="item in globalStore.mainMenu"
 | |
|               :key="item.title"
 | |
|               :to="`/${globalStore.companySlug}${item.link}`"
 | |
|               :class="[
 | |
|                 hasActiveUrl(item.link)
 | |
|                   ? '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',
 | |
|               ]"
 | |
|             >
 | |
|               {{ item.title }}
 | |
|             </router-link>
 | |
|           </div>
 | |
|         </div>
 | |
|         <div class="hidden sm:ml-6 sm:flex sm:items-center">
 | |
|           <!-- Dark mode Toggle -->
 | |
|           <LightDarkButton/>
 | |
| 
 | |
|           <!-- Profile dropdown -->
 | |
| 
 | |
|           <Menu as="div" class="ml-3 relative">
 | |
|             <BaseDropdown width-class="w-48">
 | |
|               <template #activator>
 | |
|                 <MenuButton
 | |
|                   class="
 | |
|                     bg-white
 | |
|                     flex
 | |
|                     text-sm
 | |
|                     rounded-full
 | |
|                     focus:outline-none
 | |
|                     focus:ring-2
 | |
|                     focus:ring-offset-2
 | |
|                     focus:ring-primary-500
 | |
|                   "
 | |
|                 >
 | |
|                   <img
 | |
|                     class="h-8 w-8 rounded-full"
 | |
|                     :src="previewAvatar"
 | |
|                     alt=""
 | |
|                   />
 | |
|                 </MenuButton>
 | |
|               </template>
 | |
|               <router-link :to="{ name: 'customer.profile' }">
 | |
|                 <BaseDropdownItem>
 | |
|                   <CogIcon
 | |
|                     class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500 dark:group-hover:text-gray-200"
 | |
|                     aria-hidden="true"
 | |
|                   />
 | |
|                   {{ $t('navigation.settings') }}
 | |
|                 </BaseDropdownItem>
 | |
|               </router-link>
 | |
| 
 | |
|               <BaseDropdownItem @click="logout">
 | |
|                 <LogoutIcon
 | |
|                   class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500 dark:group-hover:text-gray-200"
 | |
|                   aria-hidden="true"
 | |
|                 />
 | |
|                 {{ $t('navigation.logout') }}
 | |
|               </BaseDropdownItem>
 | |
|             </BaseDropdown>
 | |
|           </Menu>
 | |
|         </div>
 | |
|         <div class="-mr-2 flex items-center sm:hidden">
 | |
|           <!-- Mobile menu button -->
 | |
|           <DisclosureButton
 | |
|             class="
 | |
|               bg-white
 | |
|               inline-flex
 | |
|               items-center
 | |
|               justify-center
 | |
|               p-2
 | |
|               rounded-md
 | |
|               text-gray-400
 | |
|               hover:text-gray-500 hover:bg-gray-100
 | |
|               focus:outline-none
 | |
|               focus:ring-2
 | |
|               focus:ring-offset-2
 | |
|               focus:ring-primary-500
 | |
|               dark:bg-gray-700
 | |
|               dark:focus:ring-offset-gray-900
 | |
|             "
 | |
|           >
 | |
|             <span class="sr-only">Open main menu</span>
 | |
|             <MenuIcon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
 | |
|             <XIcon v-else class="block h-6 w-6" aria-hidden="true" />
 | |
|           </DisclosureButton>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <DisclosurePanel class="sm:hidden">
 | |
|       <div class="pt-2 pb-3 space-y-1">
 | |
|         <router-link
 | |
|           v-for="item in globalStore.mainMenu"
 | |
|           :key="item.title"
 | |
|           :to="`/${globalStore.companySlug}${item.link}`"
 | |
|           :class="[
 | |
|             hasActiveUrl(item.link)
 | |
|               ? 'bg-primary-50 border-primary-500 text-primary-700 dark:bg-gray-700 dark:text-primary-400'
 | |
|               : 'border-transparent text-gray-600 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800 dark:text-gray-200 dark:hover:bg-gray-700',
 | |
|             'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
 | |
|           ]"
 | |
|           :aria-current="item.current ? 'page' : undefined"
 | |
|           >{{ item.title }}
 | |
|         </router-link>
 | |
|       </div>
 | |
|       <div class="pt-4 pb-3 border-t border-gray-200 dark:border-gray-500">
 | |
|         <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="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>
 | |
|           <!-- Dark mode Toggle -->
 | |
|           <LightDarkButton/>
 | |
|         </div>
 | |
|         <div class="mt-3 space-y-1">
 | |
|           <router-link
 | |
|             v-for="item in userNavigation"
 | |
|             :key="item.title"
 | |
|             :to="item.link"
 | |
|             :class="[
 | |
|               hasActiveUrl(item.link)
 | |
|                 ? 'bg-primary-50 border-primary-500 text-primary-700'
 | |
|                 : 'border-transparent text-gray-600 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800 dark:text-gray-200 dark:hover:bg-gray-700',
 | |
|               'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
 | |
|             ]"
 | |
|             >{{ item.title }}</router-link
 | |
|           >
 | |
|         </div>
 | |
|       </div>
 | |
|     </DisclosurePanel>
 | |
|   </Disclosure>
 | |
| </template>
 | |
| 
 | |
| <script setup>
 | |
| import { useAuthStore } from '@/scripts/customer/stores/auth'
 | |
| 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,
 | |
|   DisclosurePanel,
 | |
|   Menu,
 | |
|   MenuButton,
 | |
| } from '@headlessui/vue'
 | |
| import { MenuIcon, XIcon, LogoutIcon, CogIcon } from '@heroicons/vue/outline'
 | |
| import { useI18n } from 'vue-i18n'
 | |
| 
 | |
| const { t } = useI18n()
 | |
| 
 | |
| const route = useRoute()
 | |
| const globalStore = useGlobalStore()
 | |
| 
 | |
| const userNavigation = [
 | |
|   {
 | |
|     title: t('navigation.logout'),
 | |
|     link: `/${globalStore.companySlug}/customer/login`,
 | |
|   },
 | |
| ]
 | |
| 
 | |
| const authStore = useAuthStore()
 | |
| const router = useRouter()
 | |
| const activeRoute = ref('')
 | |
| 
 | |
| const previewAvatar = computed(() => {
 | |
|   return globalStore.currentUser && globalStore.currentUser.avatar !== 0
 | |
|     ? globalStore.currentUser.avatar
 | |
|     : getDefaultAvatar()
 | |
| })
 | |
| 
 | |
| function getDefaultAvatar() {
 | |
|   const imgUrl = new URL('/img/default-avatar.jpg', import.meta.url)
 | |
|   return imgUrl
 | |
| }
 | |
| 
 | |
| watch(
 | |
|   route,
 | |
|   (val) => {
 | |
|     activeRoute.value = val.path
 | |
|   },
 | |
|   { immediate: true }
 | |
| )
 | |
| 
 | |
| const customerLogo = computed(() => {
 | |
|   if (window.customer_logo) {
 | |
|     return window.customer_logo
 | |
|   }
 | |
| 
 | |
|   return false
 | |
| })
 | |
| 
 | |
| function hasActiveUrl(url) {
 | |
|   return route.path.indexOf(url) > -1
 | |
| }
 | |
| 
 | |
| function logout() {
 | |
|   authStore.logout(globalStore.companySlug).then((res) => {
 | |
|     if (res) {
 | |
|       router.push({ name: 'customer.login' })
 | |
|     }
 | |
|   })
 | |
| }
 | |
| </script>
 |