refactor: update mobile lead/deal components
(cherry picked from commit 7e42599b494395b50305fcb806817d043d514637)
This commit is contained in:
parent
9ebd7bde2c
commit
12b92b3f21
@ -338,6 +338,7 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import DeleteLinkedDocModal from '@/components/DeleteLinkedDocModal.vue'
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
@ -420,6 +421,7 @@ const props = defineProps({
|
||||
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
const showDeleteLinkedDocModal = ref(false)
|
||||
|
||||
const { triggerOnChange, assignees, document, scripts, error } = useDocument(
|
||||
'CRM Deal',
|
||||
@ -454,7 +456,7 @@ watch(
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteDealWithModal,
|
||||
deleteDoc: deleteDeal,
|
||||
call,
|
||||
})
|
||||
document._actions = s.actions || []
|
||||
@ -496,7 +498,6 @@ const reload = ref(false)
|
||||
const showOrganizationModal = ref(false)
|
||||
const showFilesUploader = ref(false)
|
||||
const _organization = ref({})
|
||||
const showDeleteLinkedDocModal = ref(false)
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: __('Deals'), route: { name: 'Deals' } }]
|
||||
@ -742,7 +743,7 @@ function updateField(name, value) {
|
||||
})
|
||||
}
|
||||
|
||||
async function deleteDealWithModal() {
|
||||
function deleteDeal() {
|
||||
showDeleteLinkedDocModal.value = true
|
||||
}
|
||||
|
||||
|
||||
@ -185,7 +185,7 @@
|
||||
<Tooltip :text="__('Delete')">
|
||||
<div>
|
||||
<Button
|
||||
@click="deleteLeadWithModal"
|
||||
@click="deleteLead"
|
||||
variant="subtle"
|
||||
theme="red"
|
||||
icon="trash-2"
|
||||
@ -248,6 +248,7 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import DeleteLinkedDocModal from '@/components/DeleteLinkedDocModal.vue'
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
@ -297,7 +298,7 @@ import {
|
||||
usePageMeta,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
||||
import { ref, computed, watch, nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
||||
|
||||
@ -354,7 +355,7 @@ watch(
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteLeadWithModal,
|
||||
deleteDoc: deleteLead,
|
||||
call,
|
||||
})
|
||||
document._actions = s.actions || []
|
||||
@ -504,7 +505,7 @@ function updateField(name, value) {
|
||||
})
|
||||
}
|
||||
|
||||
async function deleteLeadWithModal() {
|
||||
function deleteLead() {
|
||||
showDeleteLinkedDocModal.value = true
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<LayoutHeader v-if="deal.data">
|
||||
<LayoutHeader>
|
||||
<header
|
||||
class="relative flex h-10.5 items-center justify-between gap-2 py-2.5 pl-2"
|
||||
>
|
||||
@ -10,23 +10,21 @@
|
||||
</Breadcrumbs>
|
||||
<div class="absolute right-0">
|
||||
<Dropdown
|
||||
v-if="document.doc"
|
||||
v-if="doc"
|
||||
:options="
|
||||
statusOptions(
|
||||
'deal',
|
||||
document.statuses?.length
|
||||
? document.statuses
|
||||
: deal.data._customStatuses,
|
||||
: document._statuses,
|
||||
triggerStatusChange,
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #default="{ open }">
|
||||
<Button :label="document.doc.status">
|
||||
<Button v-if="doc.status" :label="doc.status">
|
||||
<template #prefix>
|
||||
<IndicatorIcon
|
||||
:class="getDealStatus(document.doc.status).color"
|
||||
/>
|
||||
<IndicatorIcon :class="getDealStatus(doc.status).color" />
|
||||
</template>
|
||||
<template #suffix>
|
||||
<FeatherIcon
|
||||
@ -41,18 +39,14 @@
|
||||
</header>
|
||||
</LayoutHeader>
|
||||
<div
|
||||
v-if="deal.data"
|
||||
v-if="doc.name"
|
||||
class="flex h-12 items-center justify-between gap-2 border-b px-3 py-2.5"
|
||||
>
|
||||
<AssignTo
|
||||
v-model="assignees.data"
|
||||
:data="document.doc"
|
||||
doctype="CRM Deal"
|
||||
/>
|
||||
<AssignTo v-model="assignees.data" :data="doc" doctype="CRM Deal" />
|
||||
<div class="flex items-center gap-2">
|
||||
<CustomActions
|
||||
v-if="deal.data._customActions?.length"
|
||||
:actions="deal.data._customActions"
|
||||
v-if="document._actions?.length"
|
||||
:actions="document._actions"
|
||||
/>
|
||||
<CustomActions
|
||||
v-if="document.actions?.length"
|
||||
@ -60,14 +54,14 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="deal.data" class="flex h-full overflow-hidden">
|
||||
<div v-if="doc.name" class="flex h-full overflow-hidden">
|
||||
<Tabs as="div" v-model="tabIndex" :tabs="tabs" class="overflow-auto">
|
||||
<TabList class="!px-3" />
|
||||
<TabPanel v-slot="{ tab }">
|
||||
<div v-if="tab.name == 'Details'">
|
||||
<SLASection
|
||||
v-if="deal.data.sla_status"
|
||||
v-model="deal.data"
|
||||
v-if="doc.sla_status"
|
||||
v-model="doc"
|
||||
@updateField="updateField"
|
||||
/>
|
||||
<div
|
||||
@ -77,7 +71,7 @@
|
||||
<SidePanelLayout
|
||||
:sections="sections.data"
|
||||
doctype="CRM Deal"
|
||||
:docname="deal.data.name"
|
||||
:docname="dealId"
|
||||
@reload="sections.reload"
|
||||
@beforeFieldChange="beforeStatusChange"
|
||||
@afterFieldChange="reloadAssignees"
|
||||
@ -92,7 +86,7 @@
|
||||
(value, close) => {
|
||||
_contact = {
|
||||
first_name: value,
|
||||
company_name: deal.data.organization,
|
||||
company_name: doc.organization,
|
||||
}
|
||||
showContactModal = true
|
||||
close()
|
||||
@ -220,23 +214,28 @@
|
||||
<Activities
|
||||
v-else
|
||||
doctype="CRM Deal"
|
||||
:docname="dealId"
|
||||
:tabs="tabs"
|
||||
v-model:reload="reload"
|
||||
v-model:tabIndex="tabIndex"
|
||||
v-model="deal"
|
||||
@beforeSave="beforeStatusChange"
|
||||
@afterSave="reloadAssignees"
|
||||
/>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</div>
|
||||
<ErrorPage
|
||||
v-else-if="errorTitle"
|
||||
:errorTitle="errorTitle"
|
||||
:errorMessage="errorMessage"
|
||||
/>
|
||||
<OrganizationModal
|
||||
v-if="showOrganizationModal"
|
||||
v-model="showOrganizationModal"
|
||||
:data="_organization"
|
||||
:options="{
|
||||
redirect: false,
|
||||
afterInsert: (doc) => updateField('organization', doc.name),
|
||||
afterInsert: (_doc) => updateField('organization', _doc.name),
|
||||
}"
|
||||
/>
|
||||
<ContactModal
|
||||
@ -245,9 +244,16 @@
|
||||
:contact="_contact"
|
||||
:options="{
|
||||
redirect: false,
|
||||
afterInsert: (doc) => addContact(doc.name),
|
||||
afterInsert: (_doc) => addContact(_doc.name),
|
||||
}"
|
||||
/>
|
||||
<DeleteLinkedDocModal
|
||||
v-if="showDeleteLinkedDocModal"
|
||||
v-model="showDeleteLinkedDocModal"
|
||||
:doctype="'CRM Deal'"
|
||||
:docname="dealId"
|
||||
name="Deals"
|
||||
/>
|
||||
<LostReasonModal
|
||||
v-if="showLostReasonModal"
|
||||
v-model="showLostReasonModal"
|
||||
@ -255,6 +261,8 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import DeleteLinkedDocModal from '@/components/DeleteLinkedDocModal.vue'
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import DetailsIcon from '@/components/Icons/DetailsIcon.vue'
|
||||
import LoadingIndicator from '@/components/Icons/LoadingIndicator.vue'
|
||||
@ -306,7 +314,7 @@ import {
|
||||
usePageMeta,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, h, onMounted } from 'vue'
|
||||
import { ref, computed, h, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const { brand } = getSettings()
|
||||
@ -323,86 +331,57 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const deal = createResource({
|
||||
url: 'crm.fcrm.doctype.crm_deal.api.get_deal',
|
||||
params: { name: props.dealId },
|
||||
cache: ['deal', props.dealId],
|
||||
onSuccess: (data) => {
|
||||
if (data.organization) {
|
||||
organization.update({
|
||||
params: { doctype: 'CRM Organization', name: data.organization },
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
const showDeleteLinkedDocModal = ref(false)
|
||||
|
||||
const { triggerOnChange, assignees, document, scripts, error } = useDocument(
|
||||
'CRM Deal',
|
||||
props.dealId,
|
||||
)
|
||||
|
||||
const doc = computed(() => document.doc || {})
|
||||
|
||||
watch(error, (err) => {
|
||||
if (err) {
|
||||
errorTitle.value = __(
|
||||
err.exc_type == 'DoesNotExistError'
|
||||
? 'Document not found'
|
||||
: 'Error occurred',
|
||||
)
|
||||
errorMessage.value = __(err.messages?.[0] || 'An error occurred')
|
||||
} else {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => document.doc,
|
||||
async (_doc) => {
|
||||
if (scripts.data?.length) {
|
||||
let s = await setupCustomizations(scripts.data, {
|
||||
doc: _doc,
|
||||
$dialog,
|
||||
$socket,
|
||||
router,
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteDeal,
|
||||
call,
|
||||
})
|
||||
organization.fetch()
|
||||
document._actions = s.actions || []
|
||||
document._statuses = s.statuses || []
|
||||
}
|
||||
|
||||
setupCustomizations(deal, {
|
||||
doc: data,
|
||||
$dialog,
|
||||
$socket,
|
||||
router,
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteDeal,
|
||||
resource: {
|
||||
deal,
|
||||
dealContacts,
|
||||
sections,
|
||||
},
|
||||
call,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const organization = createResource({
|
||||
url: 'frappe.client.get',
|
||||
onSuccess: (data) => (deal.data._organizationObj = data),
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (deal.data) return
|
||||
deal.fetch()
|
||||
})
|
||||
{ once: true },
|
||||
)
|
||||
|
||||
const reload = ref(false)
|
||||
const showOrganizationModal = ref(false)
|
||||
const _organization = ref({})
|
||||
|
||||
function updateDeal(fieldname, value, callback) {
|
||||
value = Array.isArray(fieldname) ? '' : value
|
||||
|
||||
if (validateRequired(fieldname, value)) return
|
||||
|
||||
createResource({
|
||||
url: 'frappe.client.set_value',
|
||||
params: {
|
||||
doctype: 'CRM Deal',
|
||||
name: props.dealId,
|
||||
fieldname,
|
||||
value,
|
||||
},
|
||||
auto: true,
|
||||
onSuccess: () => {
|
||||
deal.reload()
|
||||
reload.value = true
|
||||
toast.success(__('Deal updated'))
|
||||
callback?.()
|
||||
},
|
||||
onError: (err) => {
|
||||
toast.error(err.messages?.[0] || __('Error updating deal'))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function validateRequired(fieldname, value) {
|
||||
let meta = deal.data.fields_meta || {}
|
||||
if (meta[fieldname]?.reqd && !value) {
|
||||
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: __('Deals'), route: { name: 'Deals' } }]
|
||||
|
||||
@ -423,14 +402,14 @@ const breadcrumbs = computed(() => {
|
||||
|
||||
items.push({
|
||||
label: title.value,
|
||||
route: { name: 'Deal', params: { dealId: deal.data.name } },
|
||||
route: { name: 'Deal', params: { dealId: props.dealId } },
|
||||
})
|
||||
return items
|
||||
})
|
||||
|
||||
const title = computed(() => {
|
||||
let t = doctypeMeta['CRM Deal']?.title_field || 'name'
|
||||
return deal.data?.[t] || props.dealId
|
||||
return doc.value?.[t] || props.dealId
|
||||
})
|
||||
|
||||
usePageMeta(() => {
|
||||
@ -614,26 +593,33 @@ const dealContacts = createResource({
|
||||
},
|
||||
})
|
||||
|
||||
function updateField(name, value, callback) {
|
||||
updateDeal(name, value, () => {
|
||||
deal.data[name] = value
|
||||
callback?.()
|
||||
function updateField(name, value) {
|
||||
value = Array.isArray(name) ? '' : value
|
||||
let oldValues = Array.isArray(name) ? {} : doc.value[name]
|
||||
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach((field) => (doc.value[field] = value))
|
||||
} else {
|
||||
doc.value[name] = value
|
||||
}
|
||||
|
||||
document.save.submit(null, {
|
||||
onSuccess: () => (reload.value = true),
|
||||
onError: (err) => {
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach((field) => (doc.value[field] = oldValues[field]))
|
||||
} else {
|
||||
doc.value[name] = oldValues
|
||||
}
|
||||
toast.error(err.messages?.[0] || __('Error updating field'))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function deleteDeal(name) {
|
||||
await call('frappe.client.delete', {
|
||||
doctype: 'CRM Deal',
|
||||
name,
|
||||
})
|
||||
router.push({ name: 'Deals' })
|
||||
function deleteDeal() {
|
||||
showDeleteLinkedDocModal.value = true
|
||||
}
|
||||
|
||||
const { assignees, document, triggerOnChange } = useDocument(
|
||||
'CRM Deal',
|
||||
props.dealId,
|
||||
)
|
||||
|
||||
async function triggerStatusChange(value) {
|
||||
await triggerOnChange('status', value)
|
||||
setLostReason()
|
||||
@ -643,9 +629,9 @@ const showLostReasonModal = ref(false)
|
||||
|
||||
function setLostReason() {
|
||||
if (
|
||||
getDealStatus(document.doc.status).type !== 'Lost' ||
|
||||
(document.doc.lost_reason && document.doc.lost_reason !== 'Other') ||
|
||||
(document.doc.lost_reason === 'Other' && document.doc.lost_notes)
|
||||
getDealStatus(doc.status).type !== 'Lost' ||
|
||||
(doc.lost_reason && doc.lost_reason !== 'Other') ||
|
||||
(doc.lost_reason === 'Other' && doc.lost_notes)
|
||||
) {
|
||||
document.save.submit()
|
||||
return
|
||||
@ -655,7 +641,10 @@ function setLostReason() {
|
||||
}
|
||||
|
||||
function beforeStatusChange(data) {
|
||||
if (data?.hasOwnProperty('status') && getDealStatus(data.status).type == 'Lost') {
|
||||
if (
|
||||
data?.hasOwnProperty('status') &&
|
||||
getDealStatus(data.status).type == 'Lost'
|
||||
) {
|
||||
setLostReason()
|
||||
} else {
|
||||
document.save.submit(null, {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<LayoutHeader v-if="lead.data">
|
||||
<LayoutHeader>
|
||||
<header
|
||||
class="relative flex h-10.5 items-center justify-between gap-2 py-2.5 pl-2"
|
||||
>
|
||||
@ -10,23 +10,21 @@
|
||||
</Breadcrumbs>
|
||||
<div class="absolute right-0">
|
||||
<Dropdown
|
||||
v-if="document.doc"
|
||||
v-if="doc"
|
||||
:options="
|
||||
statusOptions(
|
||||
'lead',
|
||||
document.statuses?.length
|
||||
? document.statuses
|
||||
: lead.data._customStatuses,
|
||||
: document._statuses,
|
||||
triggerStatusChange,
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #default="{ open }">
|
||||
<Button :label="document.doc.status">
|
||||
<Button v-if="doc.status" :label="doc.status">
|
||||
<template #prefix>
|
||||
<IndicatorIcon
|
||||
:class="getLeadStatus(document.doc.status).color"
|
||||
/>
|
||||
<IndicatorIcon :class="getLeadStatus(doc.status).color" />
|
||||
</template>
|
||||
<template #suffix>
|
||||
<FeatherIcon
|
||||
@ -41,18 +39,14 @@
|
||||
</header>
|
||||
</LayoutHeader>
|
||||
<div
|
||||
v-if="lead.data"
|
||||
v-if="doc.name"
|
||||
class="flex h-12 items-center justify-between gap-2 border-b px-3 py-2.5"
|
||||
>
|
||||
<AssignTo
|
||||
v-model="assignees.data"
|
||||
:data="document.doc"
|
||||
doctype="CRM Lead"
|
||||
/>
|
||||
<AssignTo v-model="assignees.data" :data="doc" doctype="CRM Lead" />
|
||||
<div class="flex items-center gap-2">
|
||||
<CustomActions
|
||||
v-if="lead.data._customActions?.length"
|
||||
:actions="lead.data._customActions"
|
||||
v-if="document._actions?.length"
|
||||
:actions="document._actions"
|
||||
/>
|
||||
<CustomActions
|
||||
v-if="document.actions?.length"
|
||||
@ -65,14 +59,14 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="lead?.data" class="flex h-full overflow-hidden">
|
||||
<div v-if="doc.name" class="flex h-full overflow-hidden">
|
||||
<Tabs as="div" v-model="tabIndex" :tabs="tabs" class="overflow-auto">
|
||||
<TabList class="!px-3" />
|
||||
<TabPanel v-slot="{ tab }">
|
||||
<div v-if="tab.name == 'Details'">
|
||||
<SLASection
|
||||
v-if="lead.data.sla_status"
|
||||
v-model="lead.data"
|
||||
v-if="doc.sla_status"
|
||||
v-model="doc"
|
||||
@updateField="updateField"
|
||||
/>
|
||||
<div
|
||||
@ -82,7 +76,7 @@
|
||||
<SidePanelLayout
|
||||
:sections="sections.data"
|
||||
doctype="CRM Lead"
|
||||
:docname="lead.data.name"
|
||||
:docname="leadId"
|
||||
@reload="sections.reload"
|
||||
@afterFieldChange="reloadAssignees"
|
||||
/>
|
||||
@ -91,16 +85,21 @@
|
||||
<Activities
|
||||
v-else
|
||||
doctype="CRM Lead"
|
||||
:docname="leadId"
|
||||
:tabs="tabs"
|
||||
v-model:reload="reload"
|
||||
v-model:tabIndex="tabIndex"
|
||||
v-model="lead"
|
||||
@beforeSave="saveChanges"
|
||||
@afterSave="reloadAssignees"
|
||||
/>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</div>
|
||||
<ErrorPage
|
||||
v-else-if="errorTitle"
|
||||
:errorTitle="errorTitle"
|
||||
:errorMessage="errorMessage"
|
||||
/>
|
||||
<Dialog
|
||||
v-model="showConvertToDealModal"
|
||||
:options="{
|
||||
@ -167,8 +166,17 @@
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
<DeleteLinkedDocModal
|
||||
v-if="showDeleteLinkedDocModal"
|
||||
v-model="showDeleteLinkedDocModal"
|
||||
:doctype="'CRM Lead'"
|
||||
:docname="leadId"
|
||||
name="Leads"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import DeleteLinkedDocModal from '@/components/DeleteLinkedDocModal.vue'
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import DetailsIcon from '@/components/Icons/DetailsIcon.vue'
|
||||
import ActivityIcon from '@/components/Icons/ActivityIcon.vue'
|
||||
@ -215,7 +223,7 @@ import {
|
||||
usePageMeta,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const { brand } = getSettings()
|
||||
@ -232,71 +240,55 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const lead = createResource({
|
||||
url: 'crm.fcrm.doctype.crm_lead.api.get_lead',
|
||||
params: { name: props.leadId },
|
||||
cache: ['lead', props.leadId],
|
||||
onSuccess: (data) => {
|
||||
setupCustomizations(lead, {
|
||||
doc: data,
|
||||
$dialog,
|
||||
$socket,
|
||||
router,
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteLead,
|
||||
resource: {
|
||||
lead,
|
||||
sections,
|
||||
},
|
||||
call,
|
||||
})
|
||||
},
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
const showDeleteLinkedDocModal = ref(false)
|
||||
|
||||
const { triggerOnChange, assignees, document, scripts, error } = useDocument(
|
||||
'CRM Lead',
|
||||
props.leadId,
|
||||
)
|
||||
|
||||
const doc = computed(() => document.doc || {})
|
||||
|
||||
watch(error, (err) => {
|
||||
if (err) {
|
||||
errorTitle.value = __(
|
||||
err.exc_type == 'DoesNotExistError'
|
||||
? 'Document not found'
|
||||
: 'Error occurred',
|
||||
)
|
||||
errorMessage.value = __(err.messages?.[0] || 'An error occurred')
|
||||
} else {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (lead.data) return
|
||||
lead.fetch()
|
||||
})
|
||||
watch(
|
||||
() => document.doc,
|
||||
async (_doc) => {
|
||||
if (scripts.data?.length) {
|
||||
let s = await setupCustomizations(scripts.data, {
|
||||
doc: _doc,
|
||||
$dialog,
|
||||
$socket,
|
||||
router,
|
||||
toast,
|
||||
updateField,
|
||||
createToast: toast.create,
|
||||
deleteDoc: deleteLead,
|
||||
call,
|
||||
})
|
||||
document._actions = s.actions || []
|
||||
document._statuses = s.statuses || []
|
||||
}
|
||||
},
|
||||
{ once: true },
|
||||
)
|
||||
|
||||
const reload = ref(false)
|
||||
|
||||
function updateLead(fieldname, value, callback) {
|
||||
value = Array.isArray(fieldname) ? '' : value
|
||||
|
||||
if (!Array.isArray(fieldname) && validateRequired(fieldname, value)) return
|
||||
|
||||
createResource({
|
||||
url: 'frappe.client.set_value',
|
||||
params: {
|
||||
doctype: 'CRM Lead',
|
||||
name: props.leadId,
|
||||
fieldname,
|
||||
value,
|
||||
},
|
||||
auto: true,
|
||||
onSuccess: () => {
|
||||
lead.reload()
|
||||
reload.value = true
|
||||
toast.success(__('Lead updated successfully'))
|
||||
callback?.()
|
||||
},
|
||||
onError: (err) => {
|
||||
toast.error(__(err.messages?.[0] || 'Error updating lead'))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function validateRequired(fieldname, value) {
|
||||
let meta = lead.data.fields_meta || {}
|
||||
if (meta[fieldname]?.reqd && !value) {
|
||||
toast.error(__('{0} is a required field', [meta[fieldname].label]))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: __('Leads'), route: { name: 'Leads' } }]
|
||||
|
||||
@ -317,14 +309,14 @@ const breadcrumbs = computed(() => {
|
||||
|
||||
items.push({
|
||||
label: title.value,
|
||||
route: { name: 'Lead', params: { leadId: lead.data.name } },
|
||||
route: { name: 'Lead', params: { leadId: props.leadId } },
|
||||
})
|
||||
return items
|
||||
})
|
||||
|
||||
const title = computed(() => {
|
||||
let t = doctypeMeta['CRM Lead']?.title_field || 'name'
|
||||
return lead.data?.[t] || props.leadId
|
||||
return doc.value?.[t] || props.leadId
|
||||
})
|
||||
|
||||
usePageMeta(() => {
|
||||
@ -412,19 +404,31 @@ const sections = createResource({
|
||||
auto: true,
|
||||
})
|
||||
|
||||
function updateField(name, value, callback) {
|
||||
updateLead(name, value, () => {
|
||||
lead.data[name] = value
|
||||
callback?.()
|
||||
function updateField(name, value) {
|
||||
value = Array.isArray(name) ? '' : value
|
||||
let oldValues = Array.isArray(name) ? {} : doc.value[name]
|
||||
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach((field) => (doc.value[field] = value))
|
||||
} else {
|
||||
doc.value[name] = value
|
||||
}
|
||||
|
||||
document.save.submit(null, {
|
||||
onSuccess: () => (reload.value = true),
|
||||
onError: (err) => {
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach((field) => (doc.value[field] = oldValues[field]))
|
||||
} else {
|
||||
doc.value[name] = oldValues
|
||||
}
|
||||
toast.error(err.messages?.[0] || __('Error updating field'))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function deleteLead(name) {
|
||||
await call('frappe.client.delete', {
|
||||
doctype: 'CRM Lead',
|
||||
name,
|
||||
})
|
||||
router.push({ name: 'Leads' })
|
||||
function deleteLead() {
|
||||
showDeleteLinkedDocModal.value = true
|
||||
}
|
||||
|
||||
// Convert to Deal
|
||||
@ -455,7 +459,7 @@ async function convertToDeal() {
|
||||
}
|
||||
|
||||
let deal = await call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
||||
lead: lead.data.name,
|
||||
lead: props.leadId,
|
||||
deal: {},
|
||||
existing_contact: existingContact.value,
|
||||
existing_organization: existingOrganization.value,
|
||||
@ -471,11 +475,6 @@ async function convertToDeal() {
|
||||
}
|
||||
}
|
||||
|
||||
const { assignees, document, triggerOnChange } = useDocument(
|
||||
'CRM Lead',
|
||||
props.leadId,
|
||||
)
|
||||
|
||||
async function triggerStatusChange(value) {
|
||||
await triggerOnChange('status', value)
|
||||
document.save.submit()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user