use tabs for search results seperation also looks better now.

This commit is contained in:
Abhinav Raut
2025-08-14 16:12:29 +05:30
parent 69accaebef
commit b971619ea6
2 changed files with 112 additions and 77 deletions

View File

@@ -1,105 +1,139 @@
<template>
<div class="max-w-5xl mx-auto p-6 min-h-screen">
<div class="space-y-8">
<div
v-for="(items, type) in results"
:key="type"
class="bg-card rounded shadow overflow-hidden"
>
<!-- Header for each section -->
<h2
class="bg-primary dark:bg-primary text-lg font-bold text-white dark:text-primary-foreground py-2 px-6 capitalize"
>
{{ type }}
</h2>
<Tabs :default-value="defaultTab" v-model="activeTab">
<TabsList class="grid w-full mb-6" :class="tabsGridClass">
<TabsTrigger v-for="(items, type) in results" :key="type" :value="type" class="capitalize">
{{ type }} ({{ items.length }})
</TabsTrigger>
</TabsList>
<!-- No results message -->
<div v-if="items.length === 0" class="p-6 text-gray-500 dark:text-muted-foreground">
{{
$t('globals.messages.noResults', {
name: type
})
}}
</div>
<TabsContent v-for="(items, type) in results" :key="type" :value="type" class="mt-0">
<div class="bg-background rounded border overflow-hidden">
<!-- No results message -->
<div v-if="items.length === 0" class="p-8 text-center text-muted-foreground">
<div class="text-lg font-medium mb-2">
{{
$t('globals.messages.noResults', {
name: type
})
}}
</div>
<div class="text-sm">{{ $t('search.adjustSearchTerms') }}</div>
</div>
<!-- Results list -->
<div class="divide-y divide-gray-200 dark:divide-border">
<div
v-for="item in items"
:key="item.id || item.uuid"
class="p-6 hover:bg-gray-100 dark:hover:bg-accent transition duration-300 ease-in-out group"
>
<router-link
:to="{
name: 'inbox-conversation',
params: {
uuid: type === 'conversations' ? item.uuid : item.conversation_uuid,
type: 'assigned'
}
}"
class="block"
<!-- Results list -->
<div v-else class="divide-y divide-border">
<div
v-for="item in items"
:key="item.id || item.uuid"
class="p-6 hover:bg-accent/50 transition duration-200 ease-in-out group"
>
<div class="flex justify-between items-start">
<div class="flex-grow">
<!-- Reference number -->
<div
class="text-sm font-semibold mb-2 group-hover:text-primary dark:group-hover:text-primary transition duration-300"
>
#{{
type === 'conversations'
? item.reference_number
: item.conversation_reference_number
}}
<router-link
:to="{
name: 'inbox-conversation',
params: {
uuid: type === 'conversations' ? item.uuid : item.conversation_uuid,
type: 'assigned'
}
}"
class="block"
>
<div class="flex justify-between items-start">
<div class="flex-grow">
<!-- Reference number -->
<div
class="text-sm font-semibold mb-2 text-muted-foreground group-hover:text-primary transition duration-200"
>
#{{
type === 'conversations'
? item.reference_number
: item.conversation_reference_number
}}
</div>
<!-- Content -->
<div
class="text-foreground font-medium mb-2 text-lg group-hover:text-primary transition duration-200"
>
{{
truncateText(
type === 'conversations' ? item.subject : item.text_content,
100
)
}}
</div>
<!-- Timestamp -->
<div class="text-sm text-muted-foreground flex items-center">
<ClockIcon class="h-4 w-4 mr-1" />
{{
formatDate(
type === 'conversations' ? item.created_at : item.conversation_created_at
)
}}
</div>
</div>
<!-- Content -->
<!-- Right arrow icon -->
<div
class="text-gray-900 dark:text-card-foreground font-medium mb-2 text-lg group-hover:text-gray-950 dark:group-hover:text-foreground transition duration-300"
class="bg-secondary rounded-full p-2 group-hover:bg-primary transition duration-200"
>
{{
truncateText(type === 'conversations' ? item.subject : item.text_content, 100)
}}
</div>
<!-- Timestamp -->
<div class="text-sm text-gray-500 dark:text-muted-foreground flex items-center">
<ClockIcon class="h-4 w-4 mr-1" />
{{
formatDate(
type === 'conversations' ? item.created_at : item.conversation_created_at
)
}}
<ChevronRightIcon
class="h-5 w-5 text-secondary-foreground group-hover:text-primary-foreground"
aria-hidden="true"
/>
</div>
</div>
<!-- Right arrow icon -->
<div
class="bg-gray-200 dark:bg-secondary rounded-full p-2 group-hover:bg-primary dark:group-hover:bg-primary transition duration-300"
>
<ChevronRightIcon
class="h-5 w-5 text-gray-700 dark:text-secondary-foreground group-hover:text-white dark:group-hover:text-primary-foreground"
aria-hidden="true"
/>
</div>
</div>
</router-link>
</router-link>
</div>
</div>
</div>
</div>
</div>
</TabsContent>
</Tabs>
</div>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import { ChevronRightIcon, ClockIcon } from 'lucide-vue-next'
import { format, parseISO } from 'date-fns'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
defineProps({
const props = defineProps({
results: {
type: Object,
required: true
}
})
// Get the first available tab as default
const defaultTab = computed(() => {
const types = Object.keys(props.results)
return types.length > 0 ? types[0] : ''
})
const activeTab = ref('')
// Watch for changes in results and set the first tab as active
watch(
() => props.results,
(newResults) => {
const types = Object.keys(newResults)
if (types.length > 0 && !activeTab.value) {
activeTab.value = types[0]
}
},
{ immediate: true }
)
// Dynamic grid class based on number of tabs
const tabsGridClass = computed(() => {
const tabCount = Object.keys(props.results).length
if (tabCount <= 2) return 'grid-cols-2'
if (tabCount <= 3) return 'grid-cols-3'
if (tabCount <= 4) return 'grid-cols-4'
return 'grid-cols-5'
})
const formatDate = (dateString) => {
const date = parseISO(dateString)
return format(date, 'MMM d, yyyy HH:mm')

View File

@@ -568,6 +568,7 @@
"search.noResultsForQuery": "No results found for query `{query}`. Try a different search term.",
"search.minQueryLength": " Please enter at least {length} characters to search.",
"search.searchBy": "Search by reference number, contact email address or messages in conversations.",
"search.adjustSearchTerms": "Try adjusting your search terms or filters.",
"sla.overdueBy": "Overdue by",
"sla.met": "SLA met",
"view.form.description": "Create and save custom filter views for quick access to your conversations.",