1<template>
2 <div class="flex flex-col">
3 <LayoutHeader>
4 <template #left-header>
5 <div class="text-lg-medium text-ink-gray-9">Call Logs</div>
6 </template>
7 <template #right-header>
8 <Button
9 label="New Call Log"
10 theme="gray"
11 variant="solid"
12 @click="newCallLog"
13 icon-left="lucide-plus"
14 />
15 </template>
16 </LayoutHeader>
17 <ListViewBuilder
18 ref="listViewRef"
19 :options="options"
20 @row-click="openCallLog"
21 />
22 <CallLogDetailModal
23 v-model="showCallLogDetailModal"
24 v-model:callLogModal="showCallLogModal"
25 :callLogId="callLogId"
26 />
27 <CallLogModal
28 v-model="showCallLogModal"
29 :callLogId="callLogId"
30 @after-insert="
31 () => {
32 listViewRef?.reload();
33 }
34 "
35 />
36 </div>
37</template>
38
39<script setup lang="ts">
40import Icon from "@opendesk/shared/Icon.vue";
41import LayoutHeader from "@/components/LayoutHeader.vue";
42import ListViewBuilder from "@/components/ListViewBuilder.vue";
43import { Avatar, Badge, Button, usePageMeta } from "frappe-ui";
44import { computed, h, ref } from "vue";
45import CallLogDetailModal from "./CallLogDetailModal.vue";
46import CallLogModal from "./CallLogModal.vue";
47import { statusColorMap, statusLabelMap } from "./utils";
48import { PhoneIcon } from "@/components/icons";
49
50const showCallLogModal = ref(false);
51const showCallLogDetailModal = ref(false);
52const callLogId = ref("");
53
54const listViewRef = ref(null);
55
56const options = computed(() => {
57 return {
58 doctype: "TP Call Log",
59 selectable: true,
60 showSelectBanner: true,
61 emptyState: {
62 title: "No Call Logs Found",
63 icon: PhoneIcon,
64 },
65 columnConfig: {
66 caller: {
67 prefix: ({ row }) => {
68 return h(Avatar, {
69 shape: "circle",
70 image: row._caller?.image || "Unknown",
71 label: row._caller?.label || "Unknown",
72 size: "sm",
73 });
74 },
75 custom: ({ row }) => {
76 return h("span", row._caller?.label || "Unknown");
77 },
78 },
79 receiver: {
80 prefix: ({ row }) => {
81 return h(Avatar, {
82 shape: "circle",
83 image: row._receiver?.image || "Unknown",
84 label: row._receiver?.label || "Unknown",
85 size: "sm",
86 });
87 },
88 custom: ({ row }) => {
89 return h("span", row._receiver?.label || "Unknown");
90 },
91 },
92 type: {
93 prefix: ({ row }) => {
94 let icon =
95 row.type === "Incoming"
96 ? "lucide-phone-incoming"
97 : "lucide-phone-outgoing";
98 return h(Icon, {
99 icon,
100 class: ["size-3 shrink-0"],
101 });
102 },
103 },
104 status: {
105 custom: ({ row }) => {
106 return h(Badge, {
107 label: statusLabelMap[row.status],
108 variant: "subtle",
109 theme: statusColorMap[row.status],
110 });
111 },
112 },
113 duration: {
114 prefix: () => {
115 return h(Icon, {
116 icon: "lucide-clock",
117 class: ["size-3 shrink-0"],
118 });
119 },
120 custom: ({ row }) => {
121 return h("span", row.duration ? row.duration + "s" : "0s");
122 },
123 },
124 },
125 };
126});
127
128const newCallLog = () => {
129 callLogId.value = "";
130 showCallLogModal.value = true;
131};
132
133function openCallLog(id: string): void {
134 callLogId.value = id;
135 showCallLogDetailModal.value = true;
136}
137
138usePageMeta(() => {
139 return {
140 title: "Call Logs",
141 };
142});
143</script>
144