1
0
forked from test/crm
jcrm/frontend/src/components/Modals/CallLogDetailModal.vue
Shariq Ansari 46ed866de6 fix: updated button with icon
(cherry picked from commit 9f3477e1cd43c7aa8144b661e7bed7ee7e8dd53b)
2025-06-16 12:19:05 +00:00

396 lines
11 KiB
Vue

<template>
<Dialog v-model="show">
<template #body>
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">
{{ __('Call Details') }}
</h3>
</div>
<div class="flex items-center gap-1">
<Dropdown
:options="[
{
group: __('Options'),
hideLabel: true,
items: [
{
label: note?.name ? __('Edit note') : __('Add note'),
icon: NoteIcon,
onClick: addEditNote,
},
{
label: task?.name ? __('Edit task') : __('Add task'),
icon: TaskIcon,
onClick: addEditTask,
},
],
},
]"
>
<template #default>
<Button variant="ghost" icon="more-horizontal" />
</template>
</Dropdown>
<Button
v-if="isManager() && !isMobileView"
variant="ghost"
class="w-7"
@click="openCallLogModal"
>
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>
<div class="flex flex-col gap-3.5">
<div
v-for="field in detailFields"
:key="field.name"
class="flex gap-2 text-base text-ink-gray-8"
>
<div class="grid size-7 place-content-center">
<component :is="field.icon" />
</div>
<div class="flex min-h-7 w-full items-center gap-2">
<div
v-if="field.name == 'receiver'"
class="flex items-center gap-1"
>
<Avatar
:image="field.value.caller.image"
:label="field.value.caller.label"
size="sm"
/>
<div class="ml-1 flex flex-col gap-1">
{{ field.value.caller.label }}
</div>
<FeatherIcon
name="arrow-right"
class="mx-1 h-4 w-4 text-ink-gray-5"
/>
<Avatar
:image="field.value.receiver.image"
:label="field.value.receiver.label"
size="sm"
/>
<div class="ml-1 flex flex-col gap-1">
{{ field.value.receiver.label }}
</div>
</div>
<Tooltip v-else-if="field.tooltip" :text="field.tooltip">
{{ field.value }}
</Tooltip>
<div class="w-full" v-else-if="field.name == 'recording_url'">
<audio
class="audio-control w-full"
controls
:src="field.value"
></audio>
</div>
<div
class="w-full cursor-pointer rounded border px-2 pt-1.5 text-base text-ink-gray-7"
v-else-if="field.name == 'note'"
@click="() => (showNoteModal = true)"
>
<FadedScrollableDiv class="max-h-24 min-h-16 overflow-y-auto">
<div
v-if="field.value?.title"
:class="[field.value?.content ? 'mb-1 font-bold' : '']"
v-html="field.value?.title"
/>
<div
v-if="field.value?.content"
v-html="field.value?.content"
/>
</FadedScrollableDiv>
</div>
<div
class="w-full cursor-pointer rounded border px-2 pt-1.5 text-base text-ink-gray-7"
v-else-if="field.name == 'task'"
@click="() => (showTaskModal = true)"
>
<FadedScrollableDiv class="max-h-24 min-h-16 overflow-y-auto">
<div
v-if="field.value?.title"
:class="[field.value?.description ? 'mb-1 font-bold' : '']"
v-html="field.value?.title"
/>
<div
v-if="field.value?.description"
v-html="field.value?.description"
/>
</FadedScrollableDiv>
</div>
<div v-else :class="field.color ? `text-${field.color}-600` : ''">
{{ field.value }}
</div>
<div v-if="field.link">
<ArrowUpRightIcon
class="h-4 w-4 shrink-0 cursor-pointer text-ink-gray-5 hover:text-ink-gray-8"
@click="() => field.link()"
/>
</div>
</div>
</div>
</div>
</div>
<div
v-if="!callLog?.data?._lead && !callLog?.data?._deal"
class="px-4 pb-7 pt-4 sm:px-6"
>
<Button
class="w-full"
variant="solid"
:label="__('Create lead')"
@click="createLead"
/>
</div>
</template>
</Dialog>
<NoteModal v-model="showNoteModal" :note="note" @after="addNoteToCallLog" />
<TaskModal v-model="showTaskModal" :task="task" @after="addTaskToCallLog" />
</template>
<script setup>
import EditIcon from '@/components/Icons/EditIcon.vue'
import ArrowUpRightIcon from '@/components/Icons/ArrowUpRightIcon.vue'
import DurationIcon from '@/components/Icons/DurationIcon.vue'
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
import Dealsicon from '@/components/Icons/DealsIcon.vue'
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
import NoteIcon from '@/components/Icons/NoteIcon.vue'
import TaskIcon from '@/components/Icons/TaskIcon.vue'
import CheckCircleIcon from '@/components/Icons/CheckCircleIcon.vue'
import NoteModal from '@/components/Modals/NoteModal.vue'
import TaskModal from '@/components/Modals/TaskModal.vue'
import FadedScrollableDiv from '@/components/FadedScrollableDiv.vue'
import { getCallLogDetail } from '@/utils/callLog'
import { usersStore } from '@/stores/users'
import { isMobileView } from '@/composables/settings'
import { useDocument } from '@/data/document'
import { FeatherIcon, Dropdown, Avatar, Tooltip, call } from 'frappe-ui'
import { ref, computed, h, nextTick, watch } from 'vue'
import { useRouter } from 'vue-router'
const { isManager } = usersStore()
const router = useRouter()
const show = defineModel()
const showNoteModal = ref(false)
const showTaskModal = ref(false)
const callLog = defineModel('callLog')
const note = ref({
title: '',
content: '',
})
const task = ref({
title: '',
description: '',
assigned_to: '',
due_date: '',
status: 'Backlog',
priority: 'Low',
})
const detailFields = computed(() => {
if (!callLog.value?.data) return []
let data = JSON.parse(JSON.stringify(callLog.value?.data))
for (const key in data) {
data[key] = getCallLogDetail(key, data)
}
note.value = data._notes?.[0] ?? null
task.value = data._tasks?.[0] ?? null
let details = [
{
icon: h(FeatherIcon, {
name: data.type.icon,
class: 'h-3.5 w-3.5',
}),
name: 'type',
value: data.type.label + ' Call',
},
{
icon: ContactsIcon,
name: 'receiver',
value: {
receiver: data.receiver,
caller: data.caller,
},
},
{
icon: data._lead ? LeadsIcon : Dealsicon,
name: 'reference_doc',
value: data._lead ? 'Lead' : 'Deal',
link: () => {
if (data._lead) {
router.push({
name: 'Lead',
params: { leadId: data._lead },
})
} else {
router.push({
name: 'Deal',
params: { dealId: data._deal },
})
}
},
condition: () => data._lead || data._deal,
},
{
icon: CalendarIcon,
name: 'creation',
value: data.creation.label,
tooltip: data.creation.label,
},
{
icon: DurationIcon,
name: 'duration',
value: data.duration.label,
},
{
icon: CheckCircleIcon,
name: 'status',
value: data.status.label,
color: data.status.color,
},
{
icon: h(FeatherIcon, {
name: 'play-circle',
class: 'h-4 w-4 mt-2',
}),
name: 'recording_url',
value: data.recording_url,
},
{
icon: NoteIcon,
name: 'note',
value: data._notes?.[0] ?? null,
},
{
icon: TaskIcon,
name: 'task',
value: data._tasks?.[0] ?? null,
},
]
return details
.filter((detail) => detail.value)
.filter((detail) => (detail.condition ? detail.condition() : true))
})
const d = ref({})
const leadDetails = ref({})
async function createLead() {
await d.value.triggerOnCreateLead?.(
callLog.value?.data,
leadDetails.value,
() => (show.value = false),
)
call('crm.fcrm.doctype.crm_call_log.crm_call_log.create_lead_from_call_log', {
call_log: callLog.value?.data,
lead_details: leadDetails.value,
}).then((d) => {
if (d) {
router.push({ name: 'Lead', params: { leadId: d } })
}
})
}
const showCallLogModal = defineModel('callLogModal')
function openCallLogModal() {
showCallLogModal.value = true
nextTick(() => {
show.value = false
})
}
function addEditNote() {
if (!note.value?.name) {
note.value = {
title: '',
content: '',
}
}
showNoteModal.value = true
}
function addEditTask() {
if (!task.value?.name) {
task.value = {
title: '',
description: '',
assigned_to: '',
due_date: '',
status: 'Backlog',
priority: 'Low',
}
}
showTaskModal.value = true
}
async function addNoteToCallLog(_note, insert_mode = false) {
note.value = _note
if (insert_mode && _note.name) {
await call('crm.integrations.api.add_note_to_call_log', {
call_sid: callLog.value?.data?.id,
note: _note,
})
}
}
async function addTaskToCallLog(_task, insert_mode = false) {
task.value = _task
if (insert_mode && _task.name) {
await call('crm.integrations.api.add_task_to_call_log', {
call_sid: callLog.value?.data?.id,
task: _task,
})
}
}
watch(
() => callLog.value?.data?.name,
(value) => {
if (!value) return
d.value = useDocument('CRM Call Log', value)
},
)
</script>
<style scoped>
.audio-control {
height: 36px;
outline: none;
border-radius: 10px;
cursor: pointer;
background-color: rgb(237, 237, 237);
}
audio::-webkit-media-controls-panel {
background-color: rgb(237, 237, 237) !important;
}
.audio-control::-webkit-media-controls-panel {
background-color: white;
}
</style>