fix: show lost reason modal if status changed to lost
(cherry picked from commit d89c304b134a7ec1f7a16bc667f2ee13858daac9) # Conflicts: # frontend/components.d.ts
This commit is contained in:
parent
9b315c2e0c
commit
a7bc3abcdd
4
frontend/components.d.ts
vendored
4
frontend/components.d.ts
vendored
@ -162,7 +162,11 @@ declare module 'vue' {
|
|||||||
ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default']
|
ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default']
|
||||||
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
||||||
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
||||||
|
<<<<<<< HEAD
|
||||||
LucideCalendar: typeof import('~icons/lucide/calendar')['default']
|
LucideCalendar: typeof import('~icons/lucide/calendar')['default']
|
||||||
|
=======
|
||||||
|
LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default']
|
||||||
|
>>>>>>> d89c304b (fix: show lost reason modal if status changed to lost)
|
||||||
LucideInfo: typeof import('~icons/lucide/info')['default']
|
LucideInfo: typeof import('~icons/lucide/info')['default']
|
||||||
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
|
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
|
||||||
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
||||||
|
|||||||
99
frontend/src/components/Modals/LostReasonModal.vue
Normal file
99
frontend/src/components/Modals/LostReasonModal.vue
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog
|
||||||
|
v-model="show"
|
||||||
|
:options="{ title: __('Lost reason') }"
|
||||||
|
@close="cancel"
|
||||||
|
>
|
||||||
|
<template #body-content>
|
||||||
|
<div class="-mt-3 mb-4 text-p-base text-ink-gray-7">
|
||||||
|
{{ __('Please provide a reason for marking this deal as lost') }}
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<div>
|
||||||
|
<div class="mb-2 text-sm text-ink-gray-5">
|
||||||
|
{{ __('Lost reason') }}
|
||||||
|
<span class="text-ink-red-2">*</span>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
class="form-control flex-1 truncate"
|
||||||
|
:value="lostReason"
|
||||||
|
doctype="CRM Lost Reason"
|
||||||
|
@change="(v) => (lostReason = v)"
|
||||||
|
:onCreate="onCreate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="mb-2 text-sm text-ink-gray-5">
|
||||||
|
{{ __('Lost notes') }}
|
||||||
|
<span v-if="lostReason == 'Other'" class="text-ink-red-2">*</span>
|
||||||
|
</div>
|
||||||
|
<FormControl
|
||||||
|
class="form-control flex-1 truncate"
|
||||||
|
type="textarea"
|
||||||
|
:value="lostNotes"
|
||||||
|
@change="(e) => (lostNotes = e.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<div class="flex justify-between items-center gap-2">
|
||||||
|
<div><ErrorMessage :message="error" /></div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button :label="__('Cancel')" @click="cancel" />
|
||||||
|
<Button variant="solid" :label="__('Save')" @click="save" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import Link from '@/components/Controls/Link.vue'
|
||||||
|
import { Dialog } from 'frappe-ui'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
deal: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const show = defineModel()
|
||||||
|
|
||||||
|
const lostReason = ref('')
|
||||||
|
const lostNotes = ref('')
|
||||||
|
const error = ref('')
|
||||||
|
|
||||||
|
function cancel() {
|
||||||
|
show.value = false
|
||||||
|
error.value = ''
|
||||||
|
lostReason.value = ''
|
||||||
|
lostNotes.value = ''
|
||||||
|
props.deal.doc.status = props.deal.originalDoc.status
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
if (!lostReason.value) {
|
||||||
|
error.value = __('Lost reason is required')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (lostReason.value === 'Other' && !lostNotes.value) {
|
||||||
|
error.value = __('Lost notes are required when lost reason is "Other"')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
error.value = ''
|
||||||
|
show.value = false
|
||||||
|
|
||||||
|
props.deal.doc.lost_reason = lostReason.value
|
||||||
|
props.deal.doc.lost_notes = lostNotes.value
|
||||||
|
props.deal.save.submit()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCreate() {
|
||||||
|
// This function can be used to handle the creation of a new lost reason
|
||||||
|
// For now, we just close the modal after creating a new reason
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -327,6 +327,11 @@
|
|||||||
:docname="props.dealId"
|
:docname="props.dealId"
|
||||||
name="Deals"
|
name="Deals"
|
||||||
/>
|
/>
|
||||||
|
<LostReasonModal
|
||||||
|
v-if="showLostReasonModal"
|
||||||
|
v-model="showLostReasonModal"
|
||||||
|
:deal="document"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import ErrorPage from '@/components/ErrorPage.vue'
|
import ErrorPage from '@/components/ErrorPage.vue'
|
||||||
@ -350,6 +355,7 @@ import AttachmentIcon from '@/components/Icons/AttachmentIcon.vue'
|
|||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import Activities from '@/components/Activities/Activities.vue'
|
import Activities from '@/components/Activities/Activities.vue'
|
||||||
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
||||||
|
import LostReasonModal from '@/components/Modals/LostReasonModal.vue'
|
||||||
import AssignTo from '@/components/AssignTo.vue'
|
import AssignTo from '@/components/AssignTo.vue'
|
||||||
import FilesUploader from '@/components/FilesUploader/FilesUploader.vue'
|
import FilesUploader from '@/components/FilesUploader/FilesUploader.vue'
|
||||||
import ContactModal from '@/components/Modals/ContactModal.vue'
|
import ContactModal from '@/components/Modals/ContactModal.vue'
|
||||||
@ -758,7 +764,22 @@ const { assignees, document, triggerOnChange } = useDocument(
|
|||||||
|
|
||||||
async function triggerStatusChange(value) {
|
async function triggerStatusChange(value) {
|
||||||
await triggerOnChange('status', value)
|
await triggerOnChange('status', value)
|
||||||
document.save.submit()
|
setLostReason()
|
||||||
|
}
|
||||||
|
|
||||||
|
const showLostReasonModal = ref(false)
|
||||||
|
|
||||||
|
function setLostReason() {
|
||||||
|
if (
|
||||||
|
document.doc.status !== 'Lost' ||
|
||||||
|
(document.doc.lost_reason && document.doc.lost_reason !== 'Other') ||
|
||||||
|
(document.doc.lost_reason === 'Other' && document.doc.lost_notes)
|
||||||
|
) {
|
||||||
|
document.save.submit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showLostReasonModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadAssignees(data) {
|
function reloadAssignees(data) {
|
||||||
|
|||||||
@ -245,6 +245,11 @@
|
|||||||
afterInsert: (doc) => addContact(doc.name),
|
afterInsert: (doc) => addContact(doc.name),
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
<LostReasonModal
|
||||||
|
v-if="showLostReasonModal"
|
||||||
|
v-model="showLostReasonModal"
|
||||||
|
:deal="document"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import Icon from '@/components/Icon.vue'
|
import Icon from '@/components/Icon.vue'
|
||||||
@ -265,6 +270,7 @@ import SuccessIcon from '@/components/Icons/SuccessIcon.vue'
|
|||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import Activities from '@/components/Activities/Activities.vue'
|
import Activities from '@/components/Activities/Activities.vue'
|
||||||
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
||||||
|
import LostReasonModal from '@/components/Modals/LostReasonModal.vue'
|
||||||
import AssignTo from '@/components/AssignTo.vue'
|
import AssignTo from '@/components/AssignTo.vue'
|
||||||
import ContactModal from '@/components/Modals/ContactModal.vue'
|
import ContactModal from '@/components/Modals/ContactModal.vue'
|
||||||
import Section from '@/components/Section.vue'
|
import Section from '@/components/Section.vue'
|
||||||
@ -627,7 +633,22 @@ const { assignees, document, triggerOnChange } = useDocument(
|
|||||||
|
|
||||||
async function triggerStatusChange(value) {
|
async function triggerStatusChange(value) {
|
||||||
await triggerOnChange('status', value)
|
await triggerOnChange('status', value)
|
||||||
document.save.submit()
|
setLostReason()
|
||||||
|
}
|
||||||
|
|
||||||
|
const showLostReasonModal = ref(false)
|
||||||
|
|
||||||
|
function setLostReason() {
|
||||||
|
if (
|
||||||
|
document.doc.status !== 'Lost' ||
|
||||||
|
(document.doc.lost_reason && document.doc.lost_reason !== 'Other') ||
|
||||||
|
(document.doc.lost_reason === 'Other' && document.doc.lost_notes)
|
||||||
|
) {
|
||||||
|
document.save.submit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showLostReasonModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadAssignees(data) {
|
function reloadAssignees(data) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user