fix: create new lead
This commit is contained in:
parent
f6eb651ed7
commit
dc9858ff87
216
frontend/src/components/NewLead.vue
Normal file
216
frontend/src/components/NewLead.vue
Normal file
@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div v-for="section in allFields" :key="section.section">
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div v-for="field in section.fields" :key="field.name">
|
||||
<div class="text-gray-600 text-sm mb-2">{{ field.label }}</div>
|
||||
<FormControl
|
||||
v-if="field.type === 'select'"
|
||||
type="select"
|
||||
:options="field.options"
|
||||
v-model="newLead[field.name]"
|
||||
>
|
||||
<template v-if="field.name == 'status'" #prefix>
|
||||
<IndicatorIcon :class="indicatorColor[newLead[field.name]]" />
|
||||
</template>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
v-else-if="field.type === 'email'"
|
||||
type="email"
|
||||
v-model="newLead[field.name]"
|
||||
/>
|
||||
<Autocomplete
|
||||
v-else-if="field.type === 'link'"
|
||||
:options="activeAgents"
|
||||
:value="getUser(newLead[field.name]).full_name"
|
||||
@change="(option) => (newLead[field.name] = option.email)"
|
||||
:placeholder="field.placeholder"
|
||||
>
|
||||
<template #prefix>
|
||||
<UserAvatar class="mr-2" :user="newLead[field.name]" size="sm" />
|
||||
</template>
|
||||
<template #item-prefix="{ option }">
|
||||
<UserAvatar class="mr-2" :user="option.email" size="sm" />
|
||||
</template>
|
||||
</Autocomplete>
|
||||
<Dropdown
|
||||
v-else-if="field.type === 'dropdown'"
|
||||
:options="statusDropdownOptions"
|
||||
class="w-full flex-1"
|
||||
>
|
||||
<template #default="{ open }">
|
||||
<Button
|
||||
:label="newLead[field.name]"
|
||||
class="justify-between w-full"
|
||||
>
|
||||
<template #prefix>
|
||||
<IndicatorIcon :class="indicatorColor[newLead[field.name]]" />
|
||||
</template>
|
||||
<template #default>{{ newLead[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="newLead[field.name]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import {
|
||||
FormControl,
|
||||
Button,
|
||||
Autocomplete,
|
||||
Dropdown,
|
||||
FeatherIcon,
|
||||
} from 'frappe-ui'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { getUser, users } = usersStore()
|
||||
const props = defineProps({
|
||||
newLead: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const statusDropdownOptions = [
|
||||
{
|
||||
label: 'New',
|
||||
icon: () => h(IndicatorIcon, { class: '!text-gray-600' }),
|
||||
onClick: () => {
|
||||
newLead.status = 'New'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Contact made',
|
||||
icon: () => h(IndicatorIcon, { class: 'text-orange-600' }),
|
||||
onClick: () => {
|
||||
newLead.status = 'Contact made'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Proposal made',
|
||||
icon: () => h(IndicatorIcon, { class: '!text-blue-600' }),
|
||||
onClick: () => {
|
||||
newLead.status = 'Proposal made'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Negotiation',
|
||||
icon: () => h(IndicatorIcon, { class: 'text-red-600' }),
|
||||
onClick: () => {
|
||||
newLead.status = 'Negotiation'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Converted',
|
||||
icon: () => h(IndicatorIcon, { class: 'text-green-600' }),
|
||||
onClick: () => {
|
||||
newLead.status = 'Converted'
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const allFields = [
|
||||
{
|
||||
section: 'Lead Details',
|
||||
fields: [
|
||||
{
|
||||
label: 'Salutation',
|
||||
name: 'salutation',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: 'Mr',
|
||||
value: 'Mr',
|
||||
},
|
||||
{
|
||||
label: 'Ms',
|
||||
value: 'Ms',
|
||||
},
|
||||
{
|
||||
label: 'Mrs',
|
||||
value: 'Mrs',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'First Name',
|
||||
name: 'first_name',
|
||||
type: 'data',
|
||||
},
|
||||
{
|
||||
label: 'Last Name',
|
||||
name: 'last_name',
|
||||
type: 'data',
|
||||
},
|
||||
{
|
||||
label: 'Email',
|
||||
name: 'email',
|
||||
type: 'data',
|
||||
},
|
||||
{
|
||||
label: 'Mobile no',
|
||||
name: 'mobile_no',
|
||||
type: 'data',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
section: 'Other Details',
|
||||
fields: [
|
||||
{
|
||||
label: 'Organization',
|
||||
name: 'organization_name',
|
||||
type: 'data',
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
name: 'status',
|
||||
type: 'select',
|
||||
options: statusDropdownOptions,
|
||||
},
|
||||
{
|
||||
label: 'Lead owner',
|
||||
name: 'lead_owner',
|
||||
type: 'link',
|
||||
placeholder: 'Lead owner',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const indicatorColor = {
|
||||
New: 'text-gray-600',
|
||||
'Contact made': 'text-orange-500',
|
||||
'Proposal made': 'text-blue-600',
|
||||
Negotiation: 'text-red-600',
|
||||
Converted: 'text-green-600',
|
||||
}
|
||||
|
||||
const activeAgents = computed(() => {
|
||||
const nonAgents = ['Administrator', 'Guest']
|
||||
return users.data
|
||||
.filter((user) => !nonAgents.includes(user.name))
|
||||
.sort((a, b) => a.full_name - b.full_name)
|
||||
.map((user) => {
|
||||
return {
|
||||
label: user.full_name,
|
||||
value: user.email,
|
||||
...user,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
@ -4,7 +4,7 @@
|
||||
<Breadcrumbs :items="[{ label: list.title }]" />
|
||||
</template>
|
||||
<template #right-header>
|
||||
<Button variant="solid" label="Create">
|
||||
<Button variant="solid" label="Create" @click="showNewDialog = true">
|
||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||
</Button>
|
||||
</template>
|
||||
@ -35,6 +35,23 @@
|
||||
</template>
|
||||
</LayoutHeader>
|
||||
<ListView :list="list" :columns="columns" :rows="rows" row-key="name" />
|
||||
<Dialog
|
||||
v-model="showNewDialog"
|
||||
:options="{
|
||||
size: '3xl',
|
||||
title: 'New Lead',
|
||||
actions: [{ label: 'Save', variant: 'solid' }],
|
||||
}"
|
||||
>
|
||||
<template #body-content>
|
||||
<NewLead :newLead="newLead" />
|
||||
</template>
|
||||
<template #actions="{ close }">
|
||||
<div class="flex flex-row-reverse gap-2">
|
||||
<Button variant="solid" label="Save" @click="createNewLead(close)" />
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -43,9 +60,18 @@ import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import Breadcrumbs from '@/components/Breadcrumbs.vue'
|
||||
import SortIcon from '@/components/Icons/SortIcon.vue'
|
||||
import FilterIcon from '@/components/Icons/FilterIcon.vue'
|
||||
import NewLead from '@/components/NewLead.vue'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { FeatherIcon, Button, Dropdown, createListResource } from 'frappe-ui'
|
||||
import { ref, computed } from 'vue'
|
||||
import {
|
||||
FeatherIcon,
|
||||
Dialog,
|
||||
Button,
|
||||
Dropdown,
|
||||
createListResource,
|
||||
createResource,
|
||||
} from 'frappe-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, computed, reactive } from 'vue'
|
||||
|
||||
const list = {
|
||||
title: 'Leads',
|
||||
@ -194,4 +220,52 @@ const indicatorColor = {
|
||||
Negotiation: 'text-red-600',
|
||||
Converted: 'text-green-600',
|
||||
}
|
||||
|
||||
const showNewDialog = ref(false)
|
||||
|
||||
let newLead = reactive({
|
||||
salutation: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
lead_name: '',
|
||||
organization_name: '',
|
||||
status: 'New',
|
||||
email: '',
|
||||
mobile_no: '',
|
||||
lead_owner: getUser().email,
|
||||
})
|
||||
|
||||
const createLead = createResource({
|
||||
url: 'frappe.client.insert',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'CRM Lead',
|
||||
...values,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function createNewLead(close) {
|
||||
createLead
|
||||
.submit(newLead, {
|
||||
validate() {
|
||||
if (!newLead.first_name) {
|
||||
return 'First name is required'
|
||||
}
|
||||
},
|
||||
onSuccess(data) {
|
||||
router.push({
|
||||
name: 'Lead',
|
||||
params: {
|
||||
leadId: data.name,
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
.then(close)
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user