fix: added lead detail section on right sidebar with phone call button and more

now agent can call the customer using that button
This commit is contained in:
Shariq Ansari 2023-08-24 00:31:05 +05:30
parent e31b6cdf72
commit d9bf3388fe
3 changed files with 157 additions and 133 deletions

View File

@ -333,8 +333,7 @@ function handleDisconnectedIncomingCall() {
counterUp.value.stop() counterUp.value.stop()
} }
async function makeOutgoingCall(close) { async function makeOutgoingCall() {
close()
if (device) { if (device) {
log.value = `Attempting to call +917666980887 ...` log.value = `Attempting to call +917666980887 ...`
@ -428,7 +427,7 @@ watch(
{ immediate: true } { immediate: true }
) )
provide('showPhoneCall', showPhoneCall) provide('makeOutgoingCall', makeOutgoingCall)
</script> </script>
<style scoped> <style scoped>

View File

@ -1,18 +1,12 @@
<template> <template>
<div class="max-w-[81.7%] pl-16 p-4 pt-2"> <div class="max-w-[81.7%] pl-16 p-4 pt-2">
<button <button
class="flex gap-2 w-full items-center rounded-lg p-1 bg-gray-100 hover:bg-gray-200" class="flex gap-2 w-full items-center rounded-lg p-2 bg-gray-100 hover:bg-gray-200"
@click="showCommunicationBox = true" @click="showCommunicationBox = true"
v-show="!showCommunicationBox" v-show="!showCommunicationBox"
> >
<UserAvatar class="m-1" :user="getUser().name" size="sm" /> <UserAvatar :user="getUser().name" size="sm" />
<div class="flex-1 text-left text-base text-gray-600">Add a reply...</div> <div class="text-base text-gray-600">Add a reply...</div>
<Tooltip text="Make a call..." class="m-1">
<PhoneIcon
class="bg-gray-900 rounded-full text-white fill-white p-[3px]"
@click.stop="showPhoneCall = true"
/>
</Tooltip>
</button> </button>
<div <div
v-show="showCommunicationBox" v-show="showCommunicationBox"
@ -55,14 +49,12 @@ import EmailEditor from '@/components/EmailEditor.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue' import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import { usersStore } from '@/stores/users' import { usersStore } from '@/stores/users'
import { Tooltip, call, Button } from 'frappe-ui' import { Tooltip, call, Button } from 'frappe-ui'
import { ref, watch, computed, defineModel, inject } from 'vue' import { ref, watch, computed, defineModel } from 'vue'
const modelValue = defineModel() const modelValue = defineModel()
const { getUser } = usersStore() const { getUser } = usersStore()
let showPhoneCall = inject('showPhoneCall')
const showCommunicationBox = ref(false) const showCommunicationBox = ref(false)
const newEmail = ref('') const newEmail = ref('')
const newEmailEditor = ref(null) const newEmailEditor = ref(null)

View File

@ -69,123 +69,148 @@
<Activities :title="tab.activityTitle" :activities="tab.content" /> <Activities :title="tab.activityTitle" :activities="tab.content" />
</TabPanel> </TabPanel>
</TabPanels> </TabPanels>
<CommunicationArea v-if="[0, 1].includes(selectedIndex)" v-model="lead" /> <CommunicationArea
v-if="[0, 1].includes(selectedIndex)"
v-model="lead"
/>
</div> </div>
<div <div class="flex flex-col justify-between border-l w-[360px]">
class="flex flex-col justify-between border-l w-[390px] overflow-hidden" <div
> class="flex flex-col gap-3 pb-4 p-5 items-center justify-center border-b"
<div class="flex flex-col gap-6.5 p-3 overflow-y-auto"> >
<div <Avatar
v-for="section in detailSections" size="3xl"
:key="section.label" :label="lead.data.first_name"
class="flex flex-col" :image="lead.data.image"
> />
<Toggler :is-opened="section.opened" v-slot="{ opened, toggle }"> <div class="font-medium text-2xl">{{ lead.data.lead_name }}</div>
<div <div class="flex gap-3">
class="flex items-center gap-2 text-base font-semibold leading-5 pl-2 pr-3 cursor-pointer max-w-fit" <Button class="rounded-full h-8 w-8" @click="makeCall">
@click="toggle()" <PhoneIcon class="h-4 w-4" />
> </Button>
<FeatherIcon <Button class="rounded-full h-8 w-8">
name="chevron-right" <EmailIcon class="h-4 w-4" />
class="h-4 text-gray-600 transition-all duration-300 ease-in-out" </Button>
:class="{ 'rotate-90': opened }" <Button icon="message-square" class="rounded-full h-8 w-8" />
/> <Button icon="more-horizontal" class="rounded-full h-8 w-8" />
{{ section.label }} </div>
</div> </div>
<transition <div class="flex-1 flex flex-col justify-between overflow-hidden">
enter-active-class="duration-300 ease-in" <div class="flex flex-col gap-6.5 p-3 overflow-y-auto">
leave-active-class="duration-300 ease-[cubic-bezier(0, 1, 0.5, 1)]" <div
enter-to-class="max-h-[200px] overflow-hidden" v-for="section in detailSections"
leave-from-class="max-h-[200px] overflow-hidden" :key="section.label"
enter-from-class="max-h-0 overflow-hidden" class="flex flex-col"
leave-to-class="max-h-0 overflow-hidden" >
> <Toggler :is-opened="section.opened" v-slot="{ opened, toggle }">
<div v-if="opened" class="flex flex-col gap-3"> <div
<div class="flex items-center gap-2 text-base font-semibold leading-5 pl-2 pr-3 cursor-pointer max-w-fit"
v-for="field in section.fields" @click="toggle()"
:key="field.label" >
class="flex items-center px-3 gap-2 text-base leading-5 first:mt-4.5" <FeatherIcon
> name="chevron-right"
<div class="text-gray-600 w-[106px]">{{ field.label }}</div> class="h-4 text-gray-600 transition-all duration-300 ease-in-out"
<div class="flex-1 w-full"> :class="{ 'rotate-90': opened }"
<FormControl />
v-if="field.type === 'select'" {{ section.label }}
type="select" </div>
:options="field.options" <transition
v-model="lead.data[field.name]" enter-active-class="duration-300 ease-in"
> leave-active-class="duration-300 ease-[cubic-bezier(0, 1, 0.5, 1)]"
<template #prefix> enter-to-class="max-h-[200px] overflow-hidden"
<IndicatorIcon leave-from-class="max-h-[200px] overflow-hidden"
:class="indicatorColor[lead.data[field.name]]" enter-from-class="max-h-0 overflow-hidden"
/> leave-to-class="max-h-0 overflow-hidden"
</template> >
</FormControl> <div v-if="opened" class="flex flex-col gap-3">
<FormControl <div
v-else-if="field.type === 'email'" v-for="field in section.fields"
type="email" :key="field.label"
v-model="lead.data[field.name]" class="flex items-center px-3 gap-2 text-base leading-5 first:mt-4.5"
/> >
<Autocomplete <div class="text-gray-600 w-[106px]">
v-else-if="field.type === 'link'" {{ field.label }}
:options="activeAgents" </div>
:value="getUser(lead.data[field.name]).full_name" <div class="flex-1 w-full">
@change=" <FormControl
(option) => (lead.data[field.name] = option.email) v-if="field.type === 'select'"
" type="select"
placeholder="Lead owner" :options="field.options"
> v-model="lead.data[field.name]"
<template #prefix> >
<UserAvatar <template #prefix>
class="mr-2" <IndicatorIcon
:user="lead.data[field.name]" :class="indicatorColor[lead.data[field.name]]"
size="sm" />
/> </template>
</template> </FormControl>
<template #item-prefix="{ option }"> <FormControl
<UserAvatar v-else-if="field.type === 'email'"
class="mr-2" type="email"
:user="option.email" v-model="lead.data[field.name]"
size="sm" />
/> <Autocomplete
</template> v-else-if="field.type === 'link'"
</Autocomplete> :options="activeAgents"
<Dropdown :value="getUser(lead.data[field.name]).full_name"
v-else-if="field.type === 'dropdown'" @change="
:options="statusDropdownOptions" (option) => (lead.data[field.name] = option.email)
class="w-full flex-1" "
> placeholder="Lead owner"
<template #default="{ open }"> >
<Button <template #prefix>
:label="lead.data[field.name]" <UserAvatar
class="justify-between w-full" class="mr-2"
> :user="lead.data[field.name]"
<template #prefix> size="sm"
<IndicatorIcon />
:class="indicatorColor[lead.data[field.name]]" </template>
/> <template #item-prefix="{ option }">
</template> <UserAvatar
<template #default>{{ class="mr-2"
lead.data[field.name] :user="option.email"
}}</template> size="sm"
<template #suffix> />
<FeatherIcon </template>
:name="open ? 'chevron-up' : 'chevron-down'" </Autocomplete>
class="h-4" <Dropdown
/> v-else-if="field.type === 'dropdown'"
</template> :options="statusDropdownOptions"
</Button> class="w-full flex-1"
</template> >
</Dropdown> <template #default="{ open }">
<FormControl <Button
v-else :label="lead.data[field.name]"
type="text" class="justify-between w-full"
v-model="lead.data[field.name]" >
/> <template #prefix>
<IndicatorIcon
:class="indicatorColor[lead.data[field.name]]"
/>
</template>
<template #default>{{
lead.data[field.name]
}}</template>
<template #suffix>
<FeatherIcon
:name="open ? 'chevron-up' : 'chevron-down'"
class="h-4"
/>
</template>
</Button>
</template>
</Dropdown>
<FormControl
v-else
type="text"
v-model="lead.data[field.name]"
/>
</div>
</div> </div>
</div> </div>
</div> </transition>
</transition> </Toggler>
</Toggler> </div>
</div> </div>
</div> </div>
<div <div
@ -217,7 +242,7 @@ import Toggler from '@/components/Toggler.vue'
import Activities from '@/components/Activities.vue' import Activities from '@/components/Activities.vue'
import Breadcrumbs from '@/components/Breadcrumbs.vue' import Breadcrumbs from '@/components/Breadcrumbs.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import CommunicationArea from '../components/CommunicationArea.vue' import CommunicationArea from '@/components/CommunicationArea.vue'
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue'
import { TransitionPresets, useTransition } from '@vueuse/core' import { TransitionPresets, useTransition } from '@vueuse/core'
import { dateFormat, timeAgo, dateTooltipFormat } from '@/utils' import { dateFormat, timeAgo, dateTooltipFormat } from '@/utils'
@ -230,11 +255,14 @@ import {
FormControl, FormControl,
Dropdown, Dropdown,
Tooltip, Tooltip,
Avatar,
} from 'frappe-ui' } from 'frappe-ui'
import { ref, computed, h } from 'vue' import { ref, computed, h, inject } from 'vue'
const { getUser, users } = usersStore() const { getUser, users } = usersStore()
const makeCall = inject('makeOutgoingCall')
const props = defineProps({ const props = defineProps({
leadId: { leadId: {
type: String, type: String,
@ -406,9 +434,14 @@ const detailSections = computed(() => {
opened: true, opened: true,
fields: [ fields: [
{ {
label: 'Name', label: 'First Name',
type: 'data', type: 'data',
name: 'lead_name', name: 'first_name',
},
{
label: 'Last Name',
type: 'data',
name: 'last_name',
}, },
{ {
label: 'Email', label: 'Email',