1<template>
2 <Tabs
3 :modelValue="activeTab"
4 @update:modelValue="changeTabTo"
5 class="flex flex-1 flex-col overflow-hidden"
6 >
7 <!-- the row carries the underline so it runs beneath the actions too -->
8 <div
9 class="flex shrink-0 items-center gap-2 border-b border-outline-gray-1 px-5"
10 >
11 <TabList size="md" class="flex-1 !border-b-0 py-1.5">
12 <TabTrigger
13 v-for="tab in tabs"
14 :key="tab.value"
15 :value="tab.value"
16 :label="tab.label"
17 :icon-left="tab.iconLeft"
18 />
19 </TabList>
20 <TicketCallActions v-if="activeTab === 'call'" />
21 </div>
22 <TabPanel
23 v-for="tab in tabs"
24 :key="tab.value"
25 :value="tab.value"
26 class="min-h-0 flex-1 flex-col overflow-auto data-[state=active]:flex"
27 >
28 <TicketAnalyticsTab v-if="tab.value === 'analytics'" />
29 <TicketTimeline
30 v-else
31 :ticket-id="String(ticket.doc?.name)"
32 :tab="tab.value"
33 :tab-label="tab.label"
34 @email:reply="(e) => communicationAreaRef?.replyToEmail(e)"
35 />
36 </TabPanel>
37 </Tabs>
38 <!-- Comm Area -->
39 <CommunicationArea
40 ref="communicationAreaRef"
41 :ticketId="String(ticket.doc?.name)"
42 :to-emails="[ticket.doc?.raised_by]"
43 :cc-emails="[]"
44 :bcc-emails="[]"
45 :key="ticket.doc?.name"
46 @update="reloadTicketFeed(String(ticket.doc?.name))"
47 />
48</template>
49
50<script setup lang="ts">
51import CommunicationArea from "@/components/CommunicationArea.vue";
52import {
53 ActivityIcon,
54 CommentIcon,
55 EmailIcon,
56 PhoneIcon,
57} from "@/components/icons";
58import TicketAnalyticsTab from "@/components/ticket-agent/analytics/TicketAnalyticsTab.vue";
59import TicketCallActions from "@/components/ticket/TicketCallActions.vue";
60import { useActiveTabManager } from "@/composables/useActiveTabManager";
61import { reloadTicketFeed } from "@/composables/useTicket";
62import { useTelephonyStore } from "@/stores/telephony";
63import { TabObject, TicketSymbol } from "@/types";
64import { TabList, TabPanel, TabTrigger, Tabs } from "frappe-ui";
65import { storeToRefs } from "pinia";
66import { computed, ComputedRef, inject, ref } from "vue";
67import LucideChartNoAxesColumn from "~icons/lucide/chart-no-axes-column";
68import TicketTimeline from "./timeline/TicketTimeline.vue";
69
70const ticket = inject(TicketSymbol)!;
71
72const communicationAreaRef = ref<InstanceType<typeof CommunicationArea> | null>(
73 null
74);
75const telephonyStore = useTelephonyStore();
76const { isCallingEnabled } = storeToRefs(telephonyStore);
77
78const tabs: ComputedRef<TabObject[]> = computed(() => {
79 const _tabs: TabObject[] = [
80 {
81 value: "activity",
82 label: "Activity",
83 iconLeft: ActivityIcon,
84 },
85 {
86 value: "email",
87 label: "Emails",
88 iconLeft: EmailIcon,
89 },
90 {
91 value: "comment",
92 label: "Comments",
93 iconLeft: CommentIcon,
94 },
95 ];
96
97 if (isCallingEnabled.value) {
98 _tabs.push({
99 value: "call",
100 label: "Calls",
101 iconLeft: PhoneIcon,
102 });
103 }
104 _tabs.push({
105 value: "analytics",
106 label: "Analytics",
107 iconLeft: LucideChartNoAxesColumn,
108 });
109 return _tabs;
110});
111
112const { activeTab, changeTabTo } = useActiveTabManager(tabs);
113</script>
114