fix: added organization link field with options and external link in lead/deal/contat page
This commit is contained in:
parent
4a089faa4d
commit
475bf6469b
16
frontend/src/components/Icons/ExternalLinkIcon.vue
Normal file
16
frontend/src/components/Icons/ExternalLinkIcon.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M5.86813 10.1317C5.67286 9.93647 5.67286 9.61988 5.86813 9.42462L12.7926 2.5001L9 2.5001C8.72386 2.5001 8.5 2.27624 8.5 2.0001C8.5 1.72396 8.72386 1.5001 9 1.5001L13.9899 1.5001C14.1076 1.49777 14.2261 1.53678 14.3215 1.61714C14.4306 1.70886 14.5 1.84638 14.5 2.0001V7.0001C14.5 7.27624 14.2761 7.5001 14 7.5001C13.7239 7.5001 13.5 7.27624 13.5 7.0001V3.20696L6.57523 10.1317C6.37997 10.327 6.06339 10.327 5.86813 10.1317ZM2.5 4.0001C2.5 3.17167 3.17157 2.5001 4 2.5001H5.8C6.07614 2.5001 6.3 2.27624 6.3 2.0001C6.3 1.72396 6.07614 1.5001 5.8 1.5001H4C2.61929 1.5001 1.5 2.61939 1.5 4.0001V12.0001C1.5 13.3808 2.61929 14.5001 4 14.5001H12C13.3807 14.5001 14.5 13.3808 14.5 12.0001V10.2001C14.5 9.92396 14.2761 9.7001 14 9.7001C13.7239 9.7001 13.5 9.92396 13.5 10.2001V12.0001C13.5 12.8285 12.8284 13.5001 12 13.5001H4C3.17157 13.5001 2.5 12.8285 2.5 12.0001V4.0001Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@ -91,10 +91,10 @@
|
||||
:key="field.name"
|
||||
class="flex items-center gap-2 px-3 text-base leading-5 last:mb-3"
|
||||
>
|
||||
<div class="w-[106px] text-gray-600">
|
||||
<div class="w-[106px] shrink-0 text-gray-600">
|
||||
{{ field.label }}
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<FormControl
|
||||
v-if="field.type === 'email'"
|
||||
type="email"
|
||||
@ -121,6 +121,11 @@
|
||||
:debounce="500"
|
||||
/>
|
||||
</div>
|
||||
<ExternalLinkIcon
|
||||
v-if="field.type === 'link' && field.link"
|
||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
||||
@click="field.link(contact[field.name])"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -197,6 +202,7 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
||||
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||
import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue'
|
||||
import LeadsListView from '@/components/ListViews/LeadsListView.vue'
|
||||
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
||||
import {
|
||||
@ -210,10 +216,12 @@ import {
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users.js'
|
||||
import { contactsStore } from '@/stores/contacts.js'
|
||||
import { organizationsStore } from '@/stores/organizations.js'
|
||||
import { ref, computed, h } from 'vue'
|
||||
|
||||
const { getContactByName, contacts } = contactsStore()
|
||||
const { getUser } = usersStore()
|
||||
const { getOrganization, organizationOptions } = organizationsStore()
|
||||
|
||||
const showContactModal = ref(false)
|
||||
|
||||
@ -297,8 +305,7 @@ const leads = createListResource({
|
||||
'first_name',
|
||||
'lead_name',
|
||||
'image',
|
||||
'organization_name',
|
||||
'organization_logo',
|
||||
'organization',
|
||||
'status',
|
||||
'email',
|
||||
'mobile_no',
|
||||
@ -320,8 +327,7 @@ const deals = createListResource({
|
||||
cache: ['deals', props.contactId],
|
||||
fields: [
|
||||
'name',
|
||||
'organization_name',
|
||||
'organization_logo',
|
||||
'organization',
|
||||
'annual_revenue',
|
||||
'deal_status',
|
||||
'email',
|
||||
@ -361,9 +367,9 @@ function getLeadRowObject(lead) {
|
||||
image: lead.image,
|
||||
image_label: lead.first_name,
|
||||
},
|
||||
organization_name: {
|
||||
label: lead.organization_name,
|
||||
logo: lead.organization_logo,
|
||||
organization: {
|
||||
label: lead.organization,
|
||||
logo: getOrganization(lead.organization)?.organization_logo,
|
||||
},
|
||||
status: {
|
||||
label: lead.status,
|
||||
@ -385,9 +391,9 @@ function getLeadRowObject(lead) {
|
||||
function getDealRowObject(deal) {
|
||||
return {
|
||||
name: deal.name,
|
||||
organization_name: {
|
||||
label: deal.organization_name,
|
||||
logo: deal.organization_logo,
|
||||
organization: {
|
||||
label: deal.organization,
|
||||
logo: getOrganization(deal.organization)?.organization_logo,
|
||||
},
|
||||
annual_revenue: formatNumberIntoCurrency(deal.annual_revenue),
|
||||
deal_status: {
|
||||
@ -415,7 +421,7 @@ const leadColumns = [
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organization_name',
|
||||
key: 'organization',
|
||||
width: '10rem',
|
||||
},
|
||||
{
|
||||
@ -448,7 +454,7 @@ const leadColumns = [
|
||||
const dealColumns = [
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organization_name',
|
||||
key: 'organization',
|
||||
width: '11rem',
|
||||
},
|
||||
{
|
||||
@ -483,54 +489,68 @@ const dealColumns = [
|
||||
},
|
||||
]
|
||||
|
||||
const details = [
|
||||
{
|
||||
label: 'Salutation',
|
||||
type: 'link',
|
||||
name: 'salutation',
|
||||
placeholder: 'Mr./Mrs./Ms.',
|
||||
options: [
|
||||
{ label: 'Dr', value: 'Dr' },
|
||||
{ label: 'Mr', value: 'Mr' },
|
||||
{ label: 'Mrs', value: 'Mrs' },
|
||||
{ label: 'Ms', value: 'Ms' },
|
||||
{ label: 'Mx', value: 'Mx' },
|
||||
{ label: 'Prof', value: 'Prof' },
|
||||
{ label: 'Master', value: 'Master' },
|
||||
{ label: 'Madam', value: 'Madam' },
|
||||
{ label: 'Miss', value: 'Miss' },
|
||||
],
|
||||
change: (data) => {
|
||||
contact.value.salutation = data.value
|
||||
updateContact('salutation', data.value)
|
||||
const details = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: 'Salutation',
|
||||
type: 'link',
|
||||
name: 'salutation',
|
||||
placeholder: 'Mr./Mrs./Ms.',
|
||||
options: [
|
||||
{ label: 'Dr', value: 'Dr' },
|
||||
{ label: 'Mr', value: 'Mr' },
|
||||
{ label: 'Mrs', value: 'Mrs' },
|
||||
{ label: 'Ms', value: 'Ms' },
|
||||
{ label: 'Mx', value: 'Mx' },
|
||||
{ label: 'Prof', value: 'Prof' },
|
||||
{ label: 'Master', value: 'Master' },
|
||||
{ label: 'Madam', value: 'Madam' },
|
||||
{ label: 'Miss', value: 'Miss' },
|
||||
],
|
||||
change: (data) => {
|
||||
contact.value.salutation = data.value
|
||||
updateContact('salutation', data.value)
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'First name',
|
||||
type: 'data',
|
||||
name: 'first_name',
|
||||
},
|
||||
{
|
||||
label: 'Last name',
|
||||
type: 'data',
|
||||
name: 'last_name',
|
||||
},
|
||||
{
|
||||
label: 'Email',
|
||||
type: 'email',
|
||||
name: 'email',
|
||||
},
|
||||
{
|
||||
label: 'Mobile no.',
|
||||
type: 'phone',
|
||||
name: 'mobile_no',
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
type: 'data',
|
||||
name: 'company_name',
|
||||
},
|
||||
]
|
||||
{
|
||||
label: 'First name',
|
||||
type: 'data',
|
||||
name: 'first_name',
|
||||
},
|
||||
{
|
||||
label: 'Last name',
|
||||
type: 'data',
|
||||
name: 'last_name',
|
||||
},
|
||||
{
|
||||
label: 'Email',
|
||||
type: 'email',
|
||||
name: 'email',
|
||||
},
|
||||
{
|
||||
label: 'Mobile no.',
|
||||
type: 'phone',
|
||||
name: 'mobile_no',
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
type: 'link',
|
||||
name: 'company_name',
|
||||
placeholder: 'Select organization',
|
||||
options: organizationOptions,
|
||||
change: (data) => {
|
||||
contact.value.company_name = data.value
|
||||
updateContact('company_name', data.value)
|
||||
},
|
||||
link: (data) => {
|
||||
router.push({
|
||||
name: 'Organization',
|
||||
params: { organizationId: data.value },
|
||||
})
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
function updateContact(fieldname, value) {
|
||||
createResource({
|
||||
@ -570,7 +590,18 @@ function updateContact(fieldname, value) {
|
||||
background: white;
|
||||
}
|
||||
|
||||
:deep(.form-control button) {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
:deep(.form-control button > div) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.form-control button svg) {
|
||||
color: white;
|
||||
width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
<Breadcrumbs :items="breadcrumbs" />
|
||||
</template>
|
||||
<template #right-header>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
type="autocomplete"
|
||||
:options="activeAgents"
|
||||
:value="getUser(deal.data.lead_owner).full_name"
|
||||
@change="(option) => updateAssignedAgent(option.email)"
|
||||
@ -16,7 +17,7 @@
|
||||
<template #item-prefix="{ option }">
|
||||
<UserAvatar class="mr-2" :user="option.email" size="sm" />
|
||||
</template>
|
||||
</Autocomplete>
|
||||
</FormControl>
|
||||
<Dropdown :options="statusDropdownOptions(deal.data, 'deal', updateDeal)">
|
||||
<template #default="{ open }">
|
||||
<Button :label="deal.data.deal_status">
|
||||
@ -45,79 +46,48 @@
|
||||
>
|
||||
About this deal
|
||||
</div>
|
||||
<FileUploader @success="changeDealImage" :validateFile="validateFile">
|
||||
<template #default="{ openFileSelector, error }">
|
||||
<div class="flex items-center justify-start gap-5 border-b p-5">
|
||||
<div class="group relative h-[88px] w-[88px]">
|
||||
<Avatar
|
||||
size="3xl"
|
||||
class="h-[88px] w-[88px]"
|
||||
:label="deal.data.organization_name"
|
||||
:image="deal.data.organization_logo"
|
||||
/>
|
||||
<Dropdown
|
||||
:options="[
|
||||
{
|
||||
icon: 'upload',
|
||||
label: deal.data.organization_logo
|
||||
? 'Change image'
|
||||
: 'Upload image',
|
||||
onClick: openFileSelector,
|
||||
},
|
||||
{
|
||||
icon: 'trash-2',
|
||||
label: 'Remove image',
|
||||
onClick: () => {
|
||||
deal.data.organization_logo = ''
|
||||
updateDeal('organization_logo', '')
|
||||
},
|
||||
},
|
||||
]"
|
||||
class="!absolute bottom-0 left-0 right-0"
|
||||
<div class="flex items-center justify-start gap-5 border-b p-5">
|
||||
<Tooltip
|
||||
text="Organization logo"
|
||||
class="group relative h-[88px] w-[88px]"
|
||||
>
|
||||
<Avatar
|
||||
size="3xl"
|
||||
class="h-[88px] w-[88px]"
|
||||
:label="organization.name"
|
||||
:image="deal.data.organization_logo"
|
||||
/>
|
||||
</Tooltip>
|
||||
<div class="flex flex-col gap-2.5 truncate">
|
||||
<Tooltip :text="organization.name">
|
||||
<div class="truncate text-2xl font-medium">
|
||||
{{ organization.name }}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div class="flex gap-1.5">
|
||||
<Tooltip text="Make a call...">
|
||||
<Button
|
||||
class="h-7 w-7"
|
||||
@click="() => makeCall(deal.data.mobile_no)"
|
||||
>
|
||||
<div
|
||||
class="z-1 absolute bottom-0 left-0 right-0 flex h-11 cursor-pointer items-center justify-center rounded-b-full bg-black bg-opacity-40 pt-3 opacity-0 duration-300 ease-in-out group-hover:opacity-100"
|
||||
style="
|
||||
-webkit-clip-path: inset(12px 0 0 0);
|
||||
clip-path: inset(12px 0 0 0);
|
||||
"
|
||||
>
|
||||
<CameraIcon class="h-6 w-6 cursor-pointer text-white" />
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2.5 truncate">
|
||||
<Tooltip :text="deal.data.organization_name">
|
||||
<div class="truncate text-2xl font-medium">
|
||||
{{ deal.data.organization_name }}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div class="flex gap-1.5">
|
||||
<Tooltip text="Make a call...">
|
||||
<Button
|
||||
class="h-7 w-7"
|
||||
@click="() => makeCall(deal.data.mobile_no)"
|
||||
>
|
||||
<PhoneIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button class="h-7 w-7">
|
||||
<EmailIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
<Tooltip text="Go to website...">
|
||||
<Button class="h-7 w-7">
|
||||
<LinkIcon
|
||||
class="h-4 w-4"
|
||||
@click="openWebsite(deal.data.website)"
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<ErrorMessage :message="error" />
|
||||
</div>
|
||||
<PhoneIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button class="h-7 w-7">
|
||||
<EmailIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
<Tooltip text="Go to website...">
|
||||
<Button class="h-7 w-7">
|
||||
<LinkIcon
|
||||
class="h-4 w-4"
|
||||
@click="openWebsite(deal.data.website)"
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
<ErrorMessage :message="error" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col justify-between overflow-hidden">
|
||||
<div class="flex flex-col overflow-y-auto">
|
||||
<div
|
||||
@ -152,10 +122,10 @@
|
||||
:key="field.label"
|
||||
class="flex items-center gap-2 px-3 text-base leading-5 first:mt-3"
|
||||
>
|
||||
<div class="w-[106px] text-gray-600">
|
||||
<div class="w-[106px] shrink-0 text-gray-600">
|
||||
{{ field.label }}
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<FormControl
|
||||
v-if="field.type === 'select'"
|
||||
type="select"
|
||||
@ -183,16 +153,18 @@
|
||||
"
|
||||
:debounce="500"
|
||||
/>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
v-else-if="field.type === 'link'"
|
||||
type="autocomplete"
|
||||
:value="deal.data[field.name]"
|
||||
:options="field.options"
|
||||
@change="(e) => field.change(e)"
|
||||
:placeholder="field.placeholder"
|
||||
class="form-control"
|
||||
/>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
v-else-if="field.type === 'user'"
|
||||
type="autocomplete"
|
||||
:options="activeAgents"
|
||||
:value="getUser(deal.data[field.name]).full_name"
|
||||
@change="(option) => updateAssignedAgent(option.email)"
|
||||
@ -221,7 +193,7 @@
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
</Autocomplete>
|
||||
</FormControl>
|
||||
<Dropdown
|
||||
v-else-if="field.type === 'dropdown'"
|
||||
:options="
|
||||
@ -283,6 +255,12 @@
|
||||
:debounce="500"
|
||||
class="form-control"
|
||||
/>
|
||||
<div
|
||||
class="flex h-7 cursor-pointer items-center px-2 py-1"
|
||||
v-else-if="field.type === 'read_only'"
|
||||
>
|
||||
{{ field.value }}
|
||||
</div>
|
||||
<FormControl
|
||||
v-else
|
||||
type="text"
|
||||
@ -294,6 +272,11 @@
|
||||
class="form-control"
|
||||
/>
|
||||
</div>
|
||||
<ExternalLinkIcon
|
||||
v-if="field.type === 'link' && field.link"
|
||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
||||
@click="field.link(deal.data[field.name])"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -311,8 +294,8 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import TaskIcon from '@/components/Icons/TaskIcon.vue'
|
||||
import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||
import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
||||
import LinkIcon from '@/components/Icons/LinkIcon.vue'
|
||||
import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue'
|
||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import Toggler from '@/components/Toggler.vue'
|
||||
import Activities from '@/components/Activities.vue'
|
||||
@ -326,12 +309,11 @@ import {
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { contactsStore } from '@/stores/contacts'
|
||||
import { organizationsStore } from '@/stores/organizations'
|
||||
import {
|
||||
createResource,
|
||||
FeatherIcon,
|
||||
FileUploader,
|
||||
ErrorMessage,
|
||||
Autocomplete,
|
||||
FormControl,
|
||||
Dropdown,
|
||||
Tooltip,
|
||||
@ -340,9 +322,12 @@ import {
|
||||
Breadcrumbs,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const { getUser, users } = usersStore()
|
||||
const { getUser } = usersStore()
|
||||
const { contacts } = contactsStore()
|
||||
const { getOrganization, organizationOptions } = organizationsStore()
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
dealId: {
|
||||
@ -394,7 +379,7 @@ function updateDeal(fieldname, value) {
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: 'Deals', route: { name: 'Deals' } }]
|
||||
items.push({
|
||||
label: deal.data.organization_name,
|
||||
label: organization.value.name,
|
||||
route: { name: 'Deal', params: { dealId: deal.data.name } },
|
||||
})
|
||||
return items
|
||||
@ -424,18 +409,6 @@ const tabs = [
|
||||
},
|
||||
]
|
||||
|
||||
function changeDealImage(file) {
|
||||
deal.data.organization_logo = file.file_url
|
||||
updateDeal('organization_logo', file.file_url)
|
||||
}
|
||||
|
||||
function validateFile(file) {
|
||||
let extn = file.name.split('.').pop().toLowerCase()
|
||||
if (!['png', 'jpg', 'jpeg'].includes(extn)) {
|
||||
return 'Only PNG and JPG images are allowed'
|
||||
}
|
||||
}
|
||||
|
||||
const detailSections = computed(() => {
|
||||
return [
|
||||
{
|
||||
@ -444,13 +417,26 @@ const detailSections = computed(() => {
|
||||
fields: [
|
||||
{
|
||||
label: 'Organization',
|
||||
type: 'data',
|
||||
name: 'organization_name',
|
||||
type: 'link',
|
||||
name: 'organization',
|
||||
placeholder: 'Select organization',
|
||||
options: organizationOptions,
|
||||
change: (data) => {
|
||||
deal.data.organization = data.value
|
||||
updateDeal('organization', data.value)
|
||||
},
|
||||
link: () => {
|
||||
router.push({
|
||||
name: 'Organization',
|
||||
params: { organizationId: organization.value.name },
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Website',
|
||||
type: 'data',
|
||||
type: 'read_only',
|
||||
name: 'website',
|
||||
value: organization.value?.website,
|
||||
},
|
||||
{
|
||||
label: 'Amount',
|
||||
@ -524,6 +510,10 @@ const detailSections = computed(() => {
|
||||
]
|
||||
})
|
||||
|
||||
const organization = computed(() => {
|
||||
return getOrganization(deal.data.organization)
|
||||
})
|
||||
|
||||
function updateAssignedAgent(email) {
|
||||
deal.data.lead_owner = email
|
||||
updateDeal('lead_owner', email)
|
||||
@ -538,7 +528,18 @@ function updateAssignedAgent(email) {
|
||||
background: white;
|
||||
}
|
||||
|
||||
:deep(.form-control button) {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
:deep(.form-control button > div) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.form-control button svg) {
|
||||
color: white;
|
||||
width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
<Breadcrumbs :items="breadcrumbs" />
|
||||
</template>
|
||||
<template #right-header>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
type="autocomplete"
|
||||
:options="activeAgents"
|
||||
:value="getUser(lead.data.lead_owner).full_name"
|
||||
@change="(option) => updateAssignedAgent(option.email)"
|
||||
@ -16,7 +17,7 @@
|
||||
<template #item-prefix="{ option }">
|
||||
<UserAvatar class="mr-2" :user="option.email" size="sm" />
|
||||
</template>
|
||||
</Autocomplete>
|
||||
</FormControl>
|
||||
<Dropdown :options="statusDropdownOptions(lead.data, 'lead', updateLead)">
|
||||
<template #default="{ open }">
|
||||
<Button :label="lead.data.status">
|
||||
@ -154,10 +155,10 @@
|
||||
:key="field.name"
|
||||
class="flex items-center gap-2 px-3 text-base leading-5 last:mb-3"
|
||||
>
|
||||
<div class="w-[106px] text-gray-600">
|
||||
<div class="w-[106px] shrink-0 text-gray-600">
|
||||
{{ field.label }}
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<FormControl
|
||||
v-if="field.type === 'select'"
|
||||
type="select"
|
||||
@ -185,16 +186,18 @@
|
||||
"
|
||||
:debounce="500"
|
||||
/>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
v-else-if="field.type === 'link'"
|
||||
type="autocomplete"
|
||||
:value="lead.data[field.name]"
|
||||
:options="field.options"
|
||||
@change="(e) => field.change(e)"
|
||||
:placeholder="field.placeholder"
|
||||
class="form-control"
|
||||
/>
|
||||
<Autocomplete
|
||||
<FormControl
|
||||
v-else-if="field.type === 'user'"
|
||||
type="autocomplete"
|
||||
:options="activeAgents"
|
||||
:value="getUser(lead.data[field.name]).full_name"
|
||||
@change="(option) => updateAssignedAgent(option.email)"
|
||||
@ -223,7 +226,7 @@
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
</Autocomplete>
|
||||
</FormControl>
|
||||
<Dropdown
|
||||
v-else-if="field.type === 'dropdown'"
|
||||
:options="
|
||||
@ -255,6 +258,12 @@
|
||||
</Button>
|
||||
</template>
|
||||
</Dropdown>
|
||||
<div
|
||||
class="flex h-7 cursor-pointer items-center px-2 py-1"
|
||||
v-else-if="field.type === 'read_only'"
|
||||
>
|
||||
{{ field.value }}
|
||||
</div>
|
||||
<FormControl
|
||||
v-else
|
||||
type="text"
|
||||
@ -266,6 +275,11 @@
|
||||
:debounce="500"
|
||||
/>
|
||||
</div>
|
||||
<ExternalLinkIcon
|
||||
v-if="field.type === 'link' && field.link"
|
||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
||||
@click="field.link(lead.data[field.name])"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -283,7 +297,9 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import TaskIcon from '@/components/Icons/TaskIcon.vue'
|
||||
import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||
import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
||||
import LinkIcon from '@/components/Icons/LinkIcon.vue'
|
||||
import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue'
|
||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import Toggler from '@/components/Toggler.vue'
|
||||
import Activities from '@/components/Activities.vue'
|
||||
@ -297,6 +313,7 @@ import {
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { contactsStore } from '@/stores/contacts'
|
||||
import { organizationsStore } from '@/stores/organizations'
|
||||
import {
|
||||
createResource,
|
||||
FileUploader,
|
||||
@ -312,10 +329,10 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import CameraIcon from '../components/Icons/CameraIcon.vue'
|
||||
|
||||
const { getUser, users } = usersStore()
|
||||
const { getUser } = usersStore()
|
||||
const { contacts } = contactsStore()
|
||||
const { getOrganization, organizationOptions } = organizationsStore()
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
@ -421,13 +438,26 @@ const detailSections = computed(() => {
|
||||
fields: [
|
||||
{
|
||||
label: 'Organization',
|
||||
type: 'data',
|
||||
name: 'organization_name',
|
||||
type: 'link',
|
||||
name: 'organization',
|
||||
placeholder: 'Select organization',
|
||||
options: organizationOptions,
|
||||
change: (data) => {
|
||||
lead.data.organization = data.value
|
||||
updateLead('organization', data.value)
|
||||
},
|
||||
link: () => {
|
||||
router.push({
|
||||
name: 'Organization',
|
||||
params: { organizationId: organization.value?.name },
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Website',
|
||||
type: 'data',
|
||||
type: 'read_only',
|
||||
name: 'website',
|
||||
value: organization.value?.website,
|
||||
},
|
||||
{
|
||||
label: 'Job title',
|
||||
@ -517,6 +547,10 @@ const detailSections = computed(() => {
|
||||
]
|
||||
})
|
||||
|
||||
const organization = computed(() => {
|
||||
return getOrganization(lead.data.organization)
|
||||
})
|
||||
|
||||
function convertToDeal() {
|
||||
lead.data.status = 'Qualified'
|
||||
lead.data.is_deal = 1
|
||||
@ -537,7 +571,18 @@ function updateAssignedAgent(email) {
|
||||
background: white;
|
||||
}
|
||||
|
||||
:deep(.form-control button) {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
:deep(.form-control button > div) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.form-control button svg) {
|
||||
color: white;
|
||||
width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user