mirror of
https://github.com/hanzoai/helpdesk.git
synced 2026-10-12 16:56:02 +00:00
fix: add empty state in contact feedback
This commit is contained in:
@@ -344,12 +344,14 @@ function onInput(e) {
|
||||
function onSelect(val) {
|
||||
if (!val) return;
|
||||
addValue(val);
|
||||
if (!error.value) {
|
||||
query.value = "";
|
||||
tempSelection.value = null;
|
||||
showOptions.value = true;
|
||||
nextTick(() => setFocus());
|
||||
if (error.value) {
|
||||
showOptions.value = false;
|
||||
return;
|
||||
}
|
||||
query.value = "";
|
||||
tempSelection.value = null;
|
||||
showOptions.value = true;
|
||||
nextTick(() => setFocus());
|
||||
}
|
||||
|
||||
// Commit the current query as a pill on Enter, comma or space.
|
||||
|
||||
@@ -12,8 +12,26 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Loading -->
|
||||
<div v-if="feedbackListResource.loading" class="flex justify-center py-10">
|
||||
<LoadingIndicator :scale="10" />
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div
|
||||
v-else-if="!feedbackListResource.data?.length"
|
||||
class="flex flex-col items-center justify-center gap-3 py-16 text-center h-full flex-1"
|
||||
>
|
||||
<LucideMessageSquare class="h-10 w-10 text-ink-gray-4" />
|
||||
<div>
|
||||
<p class="text-lg font-medium text-ink-gray-7">
|
||||
{{ __("No reviews found") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- List -->
|
||||
<div class="flex flex-col gap-2 max-h-[65vh] overflow-y-auto">
|
||||
<div v-else class="flex flex-col gap-2 max-h-[65vh] overflow-y-auto">
|
||||
<template v-for="ticket in feedbackListResource.data" :key="ticket.name">
|
||||
<div
|
||||
class="flex cursor-pointer flex-col gap-2 rounded-md border border-outline-gray-1 bg-surface-white p-2.5 hover:bg-surface-gray-1"
|
||||
@@ -75,9 +93,10 @@
|
||||
<script setup lang="ts">
|
||||
import { useContactFeedback } from "@/composables/contact";
|
||||
import { __ } from "@/translation";
|
||||
import { TabButtons, Tooltip, dayjs } from "frappe-ui";
|
||||
import { ref } from "vue";
|
||||
import { dayjs, LoadingIndicator, TabButtons, Tooltip } from "frappe-ui";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import LucideMessageSquare from "~icons/lucide/message-square";
|
||||
import LucideStar from "~icons/lucide/star";
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -158,4 +177,8 @@ function ratingBadgeClass(rating: number | undefined | null): string {
|
||||
if (stars >= 2.5) return "bg-yellow-100 text-yellow-700";
|
||||
return "bg-red-100 text-red-700";
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onSortChange(activeSort.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<div>
|
||||
<!-- make font larger -->
|
||||
<p class="text-lg font-medium text-ink-gray-7">
|
||||
{{ __("No contacts found.") }}
|
||||
{{ __("No contacts found") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
>
|
||||
<li
|
||||
:class="[
|
||||
'flex items-center rounded px-2.5 py-1.5 text-base',
|
||||
'flex items-center rounded px-2.5 py-1.5 text-base cursor-pointer',
|
||||
{ 'bg-surface-gray-2': active },
|
||||
]"
|
||||
>
|
||||
|
||||
@@ -25,6 +25,7 @@ html,
|
||||
body {
|
||||
color: var(--ink-gray-9);
|
||||
background-color: var(--surface-white);
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</PageInfo>
|
||||
<div class="overflow-y-auto flex-1">
|
||||
<div class="overflow-y-auto flex-1 flex flex-col">
|
||||
<TicketStats :dt="'Contact'" :dn="id" v-if="!isMobileView" />
|
||||
<Tabs v-model="activeTab" :tabs="tabs" class="tabs-sticky-header">
|
||||
<template #tab-item="{ tab, selected }: any">
|
||||
@@ -67,7 +67,7 @@
|
||||
</button>
|
||||
</template>
|
||||
<template #tab-panel="{ tab }">
|
||||
<div class="p-5 overflow-hidden">
|
||||
<div class="p-5 overflow-hidden flex flex-col flex-1 min-h-0">
|
||||
<TicketsTab
|
||||
v-if="tab.label === __('Tickets')"
|
||||
:doc="contact"
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</PageInfo>
|
||||
<div class="overflow-y-auto flex-1">
|
||||
<div class="overflow-y-auto flex-1 flex flex-col">
|
||||
<TicketStats
|
||||
:dt="'HD Customer'"
|
||||
:dn="customer.doc.name"
|
||||
@@ -63,21 +63,14 @@
|
||||
</button>
|
||||
</template>
|
||||
<template #tab-panel="{ tab }">
|
||||
<div class="p-5 overflow-hidden">
|
||||
<div class="p-5 overflow-hidden flex flex-col flex-1 min-h-0">
|
||||
<div v-if="tab.label === __('Tickets')">
|
||||
<!-- Tickets tab content -->
|
||||
<TicketsTab
|
||||
:doc="customer"
|
||||
:ticketsListResource="ticketsListResource"
|
||||
:baseFilter="{ customer: props.id }"
|
||||
:additionalFilter="{
|
||||
key: 'contact',
|
||||
placeholder: __('Contact'),
|
||||
doctype: 'Contact',
|
||||
filters: customer.getContacts.data?.length
|
||||
? { name: ['in', customer.getContacts.data.map((c: { contact_name: string }) => c.contact_name)] }
|
||||
: undefined,
|
||||
}"
|
||||
:additionalFilter="contactFilter"
|
||||
/>
|
||||
</div>
|
||||
<CustomerContactTab v-if="tab.label === __('Contacts')" />
|
||||
@@ -167,6 +160,22 @@ const tabs = computed(() => [
|
||||
const { doc: customer, handleDelete } = useCustomer(props.id);
|
||||
provide(CustomerResourceSymbol, customer);
|
||||
|
||||
const contactFilter = computed(() => {
|
||||
const contacts = customer.getContacts.data ?? [];
|
||||
if (contacts.length <= 1) return undefined;
|
||||
return {
|
||||
key: "contact",
|
||||
placeholder: __("Contact"),
|
||||
doctype: "Contact",
|
||||
filters: {
|
||||
name: [
|
||||
"in",
|
||||
contacts.map((c: { contact_name: string }) => c.contact_name),
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const activeTab = computed<number>({
|
||||
get() {
|
||||
const index = tabs.value.findIndex((t) => t.hash === route.hash.slice(1));
|
||||
|
||||
Reference in New Issue
Block a user