fix: moved section fields in separate component
This commit is contained in:
parent
e9cbc60675
commit
36455b8faf
86
frontend/src/components/SectionFields.vue
Normal file
86
frontend/src/components/SectionFields.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-for="field in fields"
|
||||||
|
:key="field.label"
|
||||||
|
class="flex items-center gap-2 px-3 text-base leading-5 first:mt-3"
|
||||||
|
>
|
||||||
|
<div class="w-[106px] shrink-0 text-gray-600">
|
||||||
|
{{ field.label }}
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-hidden">
|
||||||
|
<Link
|
||||||
|
v-if="field.type === 'link'"
|
||||||
|
class="form-control"
|
||||||
|
:value="data[field.name]"
|
||||||
|
:doctype="field.doctype"
|
||||||
|
:placeholder="field.placeholder"
|
||||||
|
@change="(data) => emit('update', field.name, data)"
|
||||||
|
:onCreate="field.create"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-else-if="field.type === 'select'"
|
||||||
|
class="form-control cursor-pointer [&_select]:cursor-pointer"
|
||||||
|
type="select"
|
||||||
|
:value="data[field.name]"
|
||||||
|
:options="field.options"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="emit('update', field.name, $event.target.value)"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-else-if="field.type === 'email'"
|
||||||
|
class="form-control"
|
||||||
|
type="email"
|
||||||
|
:value="data[field.name]"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="emit('update', field.name, $event.target.value)"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-else-if="field.type === 'date'"
|
||||||
|
class="form-control"
|
||||||
|
type="date"
|
||||||
|
:value="data[field.name]"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="emit('update', field.name, $event.target.value)"
|
||||||
|
/>
|
||||||
|
<Tooltip
|
||||||
|
v-else-if="field.type === 'read_only'"
|
||||||
|
class="flex h-7 cursor-pointer items-center px-2 py-1"
|
||||||
|
:text="field.tooltip"
|
||||||
|
>
|
||||||
|
{{ field.value }}
|
||||||
|
</Tooltip>
|
||||||
|
<FormControl
|
||||||
|
v-else
|
||||||
|
class="form-control"
|
||||||
|
type="text"
|
||||||
|
:value="data[field.name]"
|
||||||
|
:placeholder="field.placeholder"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="emit('update', field.name, $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ExternalLinkIcon
|
||||||
|
v-if="field.type === 'link' && field.link && data[field.name]"
|
||||||
|
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
||||||
|
@click="field.link(data[field.name])"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue'
|
||||||
|
import Link from '@/components/Controls/Link.vue'
|
||||||
|
import { FormControl, Tooltip } from 'frappe-ui'
|
||||||
|
import { defineModel } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
fields: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update'])
|
||||||
|
|
||||||
|
const data = defineModel()
|
||||||
|
</script>
|
||||||
@ -153,64 +153,12 @@
|
|||||||
leave-to-class="max-h-0 overflow-hidden"
|
leave-to-class="max-h-0 overflow-hidden"
|
||||||
>
|
>
|
||||||
<div v-if="opened" class="flex flex-col gap-1.5">
|
<div v-if="opened" class="flex flex-col gap-1.5">
|
||||||
<div
|
<SectionFields
|
||||||
v-if="section.fields"
|
v-if="section.fields"
|
||||||
v-for="field in section.fields"
|
:fields="section.fields"
|
||||||
:key="field.label"
|
v-model="deal.data"
|
||||||
class="flex items-center gap-2 px-3 text-base leading-5 first:mt-3"
|
@update="updateField"
|
||||||
>
|
|
||||||
<div class="w-[106px] shrink-0 text-gray-600">
|
|
||||||
{{ field.label }}
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 overflow-hidden">
|
|
||||||
<Link
|
|
||||||
v-if="field.type === 'link'"
|
|
||||||
class="form-control"
|
|
||||||
:value="deal.data[field.name]"
|
|
||||||
:doctype="field.doctype"
|
|
||||||
:placeholder="field.placeholder"
|
|
||||||
@change="(e) => field.change(e)"
|
|
||||||
:onCreate="field.create"
|
|
||||||
/>
|
/>
|
||||||
<FormControl
|
|
||||||
v-else-if="field.type === 'date'"
|
|
||||||
type="date"
|
|
||||||
:value="deal.data[field.name]"
|
|
||||||
@change.stop="
|
|
||||||
updateDeal(field.name, $event.target.value)
|
|
||||||
"
|
|
||||||
:debounce="500"
|
|
||||||
class="form-control"
|
|
||||||
/>
|
|
||||||
<Tooltip
|
|
||||||
:text="field.tooltip"
|
|
||||||
class="flex h-7 cursor-pointer items-center px-2 py-1"
|
|
||||||
v-else-if="field.type === 'read_only'"
|
|
||||||
>
|
|
||||||
{{ field.value }}
|
|
||||||
</Tooltip>
|
|
||||||
<FormControl
|
|
||||||
v-else
|
|
||||||
class="form-control"
|
|
||||||
type="text"
|
|
||||||
:value="deal.data[field.name]"
|
|
||||||
@change.stop="
|
|
||||||
updateDeal(field.name, $event.target.value)
|
|
||||||
"
|
|
||||||
:debounce="500"
|
|
||||||
:placeholder="field.placeholder"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ExternalLinkIcon
|
|
||||||
v-if="
|
|
||||||
field.type === 'link' &&
|
|
||||||
field.link &&
|
|
||||||
deal.data[field.name]
|
|
||||||
"
|
|
||||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
|
||||||
@click="field.link(deal.data[field.name])"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div
|
<div
|
||||||
v-if="section.contacts.length"
|
v-if="section.contacts.length"
|
||||||
@ -360,6 +308,7 @@ import UserAvatar from '@/components/UserAvatar.vue'
|
|||||||
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
||||||
import ContactModal from '@/components/Modals/ContactModal.vue'
|
import ContactModal from '@/components/Modals/ContactModal.vue'
|
||||||
import Link from '@/components/Controls/Link.vue'
|
import Link from '@/components/Controls/Link.vue'
|
||||||
|
import SectionFields from '@/components/SectionFields.vue'
|
||||||
import {
|
import {
|
||||||
dealStatuses,
|
dealStatuses,
|
||||||
statusDropdownOptions,
|
statusDropdownOptions,
|
||||||
|
|||||||
@ -162,108 +162,11 @@
|
|||||||
leave-to-class="max-h-0 overflow-hidden"
|
leave-to-class="max-h-0 overflow-hidden"
|
||||||
>
|
>
|
||||||
<div v-if="opened" class="flex flex-col gap-1.5 px-3">
|
<div v-if="opened" class="flex flex-col gap-1.5 px-3">
|
||||||
<div
|
<SectionFields
|
||||||
v-for="field in section.fields"
|
:fields="section.fields"
|
||||||
:key="field.name"
|
v-model="lead.data"
|
||||||
class="flex items-center gap-2 px-3 text-base leading-5 last:mb-3"
|
@update="updateField"
|
||||||
>
|
|
||||||
<div class="w-[106px] shrink-0 text-gray-600">
|
|
||||||
{{ field.label }}
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 overflow-hidden">
|
|
||||||
<FormControl
|
|
||||||
v-if="field.type === 'select'"
|
|
||||||
class="form-control cursor-pointer [&_select]:cursor-pointer"
|
|
||||||
type="select"
|
|
||||||
:options="field.options"
|
|
||||||
:value="lead.data[field.name]"
|
|
||||||
@change.stop="
|
|
||||||
updateLead(field.name, $event.target.value)
|
|
||||||
"
|
|
||||||
:debounce="500"
|
|
||||||
/>
|
/>
|
||||||
<FormControl
|
|
||||||
v-else-if="field.type === 'email'"
|
|
||||||
type="email"
|
|
||||||
class="form-control"
|
|
||||||
:value="lead.data[field.name]"
|
|
||||||
@change.stop="
|
|
||||||
updateLead(field.name, $event.target.value)
|
|
||||||
"
|
|
||||||
:debounce="500"
|
|
||||||
/>
|
|
||||||
<Link
|
|
||||||
v-else-if="field.type === 'link'"
|
|
||||||
class="form-control"
|
|
||||||
:value="lead.data[field.name]"
|
|
||||||
:doctype="field.doctype"
|
|
||||||
:placeholder="field.placeholder"
|
|
||||||
@change="(data) => updateField(field.name, data)"
|
|
||||||
:onCreate="field.create"
|
|
||||||
/>
|
|
||||||
<FormControl
|
|
||||||
v-else-if="field.type === 'user'"
|
|
||||||
type="autocomplete"
|
|
||||||
:options="activeAgents"
|
|
||||||
:value="getUser(lead.data[field.name]).full_name"
|
|
||||||
@change="
|
|
||||||
(option) => updateField('lead_owner', option.email)
|
|
||||||
"
|
|
||||||
class="form-control"
|
|
||||||
:placeholder="field.placeholder"
|
|
||||||
>
|
|
||||||
<template #target="{ togglePopover }">
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
@click="togglePopover()"
|
|
||||||
:label="getUser(lead.data[field.name]).full_name"
|
|
||||||
class="w-full !justify-start"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<UserAvatar
|
|
||||||
:user="lead.data[field.name]"
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
<template #item-prefix="{ option }">
|
|
||||||
<UserAvatar
|
|
||||||
class="mr-2"
|
|
||||||
:user="option.email"
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</FormControl>
|
|
||||||
<Tooltip
|
|
||||||
:text="field.tooltip"
|
|
||||||
class="flex h-7 cursor-pointer items-center px-2 py-1"
|
|
||||||
v-else-if="field.type === 'read_only'"
|
|
||||||
>
|
|
||||||
{{ field.value || lead.data[field.name] }}
|
|
||||||
</Tooltip>
|
|
||||||
<FormControl
|
|
||||||
v-else
|
|
||||||
type="text"
|
|
||||||
:value="lead.data[field.name]"
|
|
||||||
:placeholder="field.placeholder"
|
|
||||||
@change.stop="
|
|
||||||
updateLead(field.name, $event.target.value)
|
|
||||||
"
|
|
||||||
class="form-control"
|
|
||||||
:debounce="500"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ExternalLinkIcon
|
|
||||||
v-if="
|
|
||||||
field.type === 'link' &&
|
|
||||||
field.link &&
|
|
||||||
lead.data[field.name]
|
|
||||||
"
|
|
||||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600"
|
|
||||||
@click="field.link(lead.data[field.name])"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</Toggler>
|
</Toggler>
|
||||||
@ -293,13 +196,12 @@ import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
|||||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||||
import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
import CameraIcon from '@/components/Icons/CameraIcon.vue'
|
||||||
import LinkIcon from '@/components/Icons/LinkIcon.vue'
|
import LinkIcon from '@/components/Icons/LinkIcon.vue'
|
||||||
import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue'
|
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import Toggler from '@/components/Toggler.vue'
|
import Toggler from '@/components/Toggler.vue'
|
||||||
import Activities from '@/components/Activities.vue'
|
import Activities from '@/components/Activities.vue'
|
||||||
import UserAvatar from '@/components/UserAvatar.vue'
|
import UserAvatar from '@/components/UserAvatar.vue'
|
||||||
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
||||||
import Link from '@/components/Controls/Link.vue'
|
import SectionFields from '@/components/SectionFields.vue'
|
||||||
import {
|
import {
|
||||||
leadStatuses,
|
leadStatuses,
|
||||||
statusDropdownOptions,
|
statusDropdownOptions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user