1<template>
2 <div class="flex-1 overflow-y-auto">
3 <div
4 v-if="analytics.data"
5 class="mx-auto flex w-full max-w-6xl flex-col gap-4 px-5 py-4"
6 >
7 <TicketTimeline
8 :timeline="analytics.data.timeline"
9 :events="analytics.data.events"
10 />
11 <div class="grid items-start gap-4 lg:grid-cols-2">
12 <ConversationSummary :summary="analytics.data.summary" />
13 <AnalyticsMetricCards :metrics="analytics.data.metrics" />
14 </div>
15 </div>
16 <div
17 v-else-if="analytics.error"
18 class="flex h-full flex-col items-center justify-center gap-3"
19 >
20 <p class="text-p-base text-ink-gray-6">
21 {{ __("Failed to load analytics") }}
22 </p>
23 <Button :label="__('Retry')" @click="analytics.reload()" />
24 </div>
25 <div v-else class="flex h-full flex-col items-center justify-center">
26 <LoadingIndicator class="size-8" />
27 </div>
28 </div>
29</template>
30
31<script setup lang="ts">
32import { useTicket } from "@/composables/useTicket";
33import { TicketSymbol } from "@/types";
34import { Button, LoadingIndicator } from "frappe-ui";
35import { computed, inject, watch } from "vue";
36import AnalyticsMetricCards from "./AnalyticsMetricCards.vue";
37import ConversationSummary from "./ConversationSummary.vue";
38import TicketTimeline from "./TicketTimeline.vue";
39
40const ticket = inject(TicketSymbol)!;
41const ticketId = computed(() => String(ticket.value.doc.name));
42const analytics = computed(() => useTicket(ticketId.value).analytics);
43
44// status and priority changes rewrite the SLA picture (hold, due dates), so
45// the analytics must refetch, not just on ticket switch
46watch(
47 () => [ticketId.value, ticket.value.doc.status, ticket.value.doc.priority],
48 () => analytics.value.reload(),
49 { immediate: true }
50);
51</script>
52