mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			198 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script setup>
 | |
| import { ref, computed } from 'vue';
 | |
| import { useI18n } from 'vue-i18n';
 | |
| import { useRoute } from 'vue-router';
 | |
| import { OnClickOutside } from '@vueuse/components';
 | |
| import {
 | |
|   ARTICLE_TABS,
 | |
|   CATEGORY_ALL,
 | |
|   ARTICLE_TABS_OPTIONS,
 | |
| } from 'dashboard/helper/portalHelper';
 | |
| 
 | |
| import TabBar from 'dashboard/components-next/tabbar/TabBar.vue';
 | |
| import Button from 'dashboard/components-next/button/Button.vue';
 | |
| import DropdownMenu from 'dashboard/components-next/dropdown-menu/DropdownMenu.vue';
 | |
| 
 | |
| const props = defineProps({
 | |
|   categories: {
 | |
|     type: Array,
 | |
|     required: true,
 | |
|   },
 | |
|   allowedLocales: {
 | |
|     type: Array,
 | |
|     required: true,
 | |
|   },
 | |
|   meta: {
 | |
|     type: Object,
 | |
|     required: true,
 | |
|   },
 | |
| });
 | |
| 
 | |
| const emit = defineEmits([
 | |
|   'tabChange',
 | |
|   'localeChange',
 | |
|   'categoryChange',
 | |
|   'newArticle',
 | |
| ]);
 | |
| 
 | |
| const route = useRoute();
 | |
| const { t } = useI18n();
 | |
| 
 | |
| const isCategoryMenuOpen = ref(false);
 | |
| const isLocaleMenuOpen = ref(false);
 | |
| 
 | |
| const countKey = tab => {
 | |
|   if (tab.value === 'all') {
 | |
|     return 'articlesCount';
 | |
|   }
 | |
|   return `${tab.value}ArticlesCount`;
 | |
| };
 | |
| 
 | |
| const tabs = computed(() => {
 | |
|   return ARTICLE_TABS_OPTIONS.map(tab => ({
 | |
|     label: t(`HELP_CENTER.ARTICLES_PAGE.ARTICLES_HEADER.TABS.${tab.key}`),
 | |
|     value: tab.value,
 | |
|     count: props.meta[countKey(tab)],
 | |
|   }));
 | |
| });
 | |
| 
 | |
| const activeTabIndex = computed(() => {
 | |
|   const tabParam = route.params.tab || ARTICLE_TABS.ALL;
 | |
|   return tabs.value.findIndex(tab => tab.value === tabParam);
 | |
| });
 | |
| 
 | |
| const activeCategoryName = computed(() => {
 | |
|   const activeCategory = props.categories.find(
 | |
|     category => category.slug === route.params.categorySlug
 | |
|   );
 | |
| 
 | |
|   if (activeCategory) {
 | |
|     const { icon, name } = activeCategory;
 | |
|     return `${icon} ${name}`;
 | |
|   }
 | |
| 
 | |
|   return t('HELP_CENTER.ARTICLES_PAGE.ARTICLES_HEADER.CATEGORY.ALL');
 | |
| });
 | |
| 
 | |
| const activeLocaleName = computed(() => {
 | |
|   return props.allowedLocales.find(
 | |
|     locale => locale.code === route.params.locale
 | |
|   )?.name;
 | |
| });
 | |
| 
 | |
| const categoryMenuItems = computed(() => {
 | |
|   const defaultMenuItem = {
 | |
|     label: t('HELP_CENTER.ARTICLES_PAGE.ARTICLES_HEADER.CATEGORY.ALL'),
 | |
|     value: CATEGORY_ALL,
 | |
|     action: 'filter',
 | |
|   };
 | |
| 
 | |
|   const categoryItems = props.categories.map(category => ({
 | |
|     label: category.name,
 | |
|     value: category.slug,
 | |
|     action: 'filter',
 | |
|     emoji: category.icon,
 | |
|   }));
 | |
| 
 | |
|   const hasCategorySlug = !!route.params.categorySlug;
 | |
| 
 | |
|   return hasCategorySlug ? [defaultMenuItem, ...categoryItems] : categoryItems;
 | |
| });
 | |
| 
 | |
| const hasCategoryMenuItems = computed(() => {
 | |
|   return categoryMenuItems.value?.length > 0;
 | |
| });
 | |
| 
 | |
| const localeMenuItems = computed(() => {
 | |
|   return props.allowedLocales.map(locale => ({
 | |
|     label: locale.name,
 | |
|     value: locale.code,
 | |
|     action: 'filter',
 | |
|   }));
 | |
| });
 | |
| 
 | |
| const hasMoreThanOneLocaleMenuItems = computed(() => {
 | |
|   return localeMenuItems.value?.length > 1;
 | |
| });
 | |
| 
 | |
| const handleLocaleAction = ({ value }) => {
 | |
|   emit('localeChange', value);
 | |
|   isLocaleMenuOpen.value = false;
 | |
| };
 | |
| 
 | |
| const handleCategoryAction = ({ value }) => {
 | |
|   emit('categoryChange', value);
 | |
|   isCategoryMenuOpen.value = false;
 | |
| };
 | |
| 
 | |
| const handleNewArticle = () => {
 | |
|   emit('newArticle');
 | |
| };
 | |
| 
 | |
| const handleTabChange = value => {
 | |
|   emit('tabChange', value);
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div class="flex flex-col items-start w-full gap-2 lg:flex-row">
 | |
|     <TabBar
 | |
|       class="bg-n-solid-1"
 | |
|       :tabs="tabs"
 | |
|       :initial-active-tab="activeTabIndex"
 | |
|       @tab-changed="handleTabChange"
 | |
|     />
 | |
|     <div class="flex items-start justify-between w-full gap-2">
 | |
|       <div class="flex items-center gap-2">
 | |
|         <div v-if="hasMoreThanOneLocaleMenuItems" class="relative group">
 | |
|           <OnClickOutside @trigger="isLocaleMenuOpen = false">
 | |
|             <Button
 | |
|               :label="activeLocaleName"
 | |
|               size="sm"
 | |
|               icon-position="right"
 | |
|               icon="chevron-lucide-down"
 | |
|               icon-lib="lucide"
 | |
|               variant="secondary"
 | |
|               @click="isLocaleMenuOpen = !isLocaleMenuOpen"
 | |
|             />
 | |
| 
 | |
|             <DropdownMenu
 | |
|               v-if="isLocaleMenuOpen"
 | |
|               :menu-items="localeMenuItems"
 | |
|               class="left-0 w-40 max-w-[300px] mt-2 overflow-y-auto xl:right-0 top-full max-h-60"
 | |
|               @action="handleLocaleAction"
 | |
|             />
 | |
|           </OnClickOutside>
 | |
|         </div>
 | |
|         <div v-if="hasCategoryMenuItems" class="relative group">
 | |
|           <OnClickOutside @trigger="isCategoryMenuOpen = false">
 | |
|             <Button
 | |
|               :label="activeCategoryName"
 | |
|               size="sm"
 | |
|               icon-position="right"
 | |
|               icon="chevron-lucide-down"
 | |
|               icon-lib="lucide"
 | |
|               variant="secondary"
 | |
|               class="max-w-48"
 | |
|               @click="isCategoryMenuOpen = !isCategoryMenuOpen"
 | |
|             />
 | |
| 
 | |
|             <DropdownMenu
 | |
|               v-if="isCategoryMenuOpen"
 | |
|               :menu-items="categoryMenuItems"
 | |
|               class="left-0 w-48 mt-2 overflow-y-auto xl:right-0 top-full max-h-60"
 | |
|               @action="handleCategoryAction"
 | |
|             />
 | |
|           </OnClickOutside>
 | |
|         </div>
 | |
|       </div>
 | |
|       <Button
 | |
|         :label="t('HELP_CENTER.ARTICLES_PAGE.ARTICLES_HEADER.NEW_ARTICLE')"
 | |
|         icon="add"
 | |
|         size="sm"
 | |
|         @click="handleNewArticle"
 | |
|       />
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | 
