feat: show formatted currency fields in Modal & data fields

This commit is contained in:
Shariq Ansari 2024-12-25 17:57:38 +05:30
parent 9b8662de14
commit 0d2ca4cb4a
15 changed files with 71 additions and 11 deletions

View File

@ -32,7 +32,12 @@
<span>{{ __('Loading...') }}</span> <span>{{ __('Loading...') }}</span>
</div> </div>
<div v-else> <div v-else>
<FieldLayout v-if="tabs.data" :tabs="tabs.data" :data="data.doc" /> <FieldLayout
v-if="tabs.data"
:tabs="tabs.data"
:data="data.doc"
:doctype="doctype"
/>
</div> </div>
<DataFieldsModal <DataFieldsModal
v-if="showDataFieldsModal" v-if="showDataFieldsModal"

View File

@ -190,6 +190,16 @@
:placeholder="getPlaceholder(field)" :placeholder="getPlaceholder(field)"
v-model="data[field.name]" v-model="data[field.name]"
/> />
<FormControl
v-else-if="field.type === 'Currency'"
type="text"
:value="getFormattedCurrency(field.name, data)"
:placeholder="getPlaceholder(field)"
:disabled="Boolean(field.read_only)"
@change="
data[field.name] = flt($event.target.value)
"
/>
<FormControl <FormControl
v-else v-else
type="text" type="text"
@ -213,22 +223,29 @@ import EditIcon from '@/components/Icons/EditIcon.vue'
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue' import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import Link from '@/components/Controls/Link.vue' import Link from '@/components/Controls/Link.vue'
import { getMeta } from '../stores/meta'
import { usersStore } from '@/stores/users' import { usersStore } from '@/stores/users'
import { getFormat } from '@/utils' import { getFormat } from '@/utils'
import { flt } from '@/utils/numberFormat.js'
import { Tabs, Tooltip, DatePicker, DateTimePicker } from 'frappe-ui' import { Tabs, Tooltip, DatePicker, DateTimePicker } from 'frappe-ui'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
const { getUser } = usersStore()
const props = defineProps({ const props = defineProps({
tabs: Array, tabs: Array,
data: Object, data: Object,
doctype: {
type: String,
default: 'CRM Lead',
},
modal: { modal: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}) })
const { getFormattedCurrency } = getMeta(props.doctype)
const { getUser } = usersStore()
const hasTabs = computed(() => !props.tabs[0].no_tabs) const hasTabs = computed(() => !props.tabs[0].no_tabs)
const tabIndex = ref(0) const tabIndex = ref(0)

View File

@ -23,7 +23,7 @@
</div> </div>
</div> </div>
<div v-if="tabs.data"> <div v-if="tabs.data">
<FieldLayout :tabs="tabs.data" :data="_address" /> <FieldLayout :tabs="tabs.data" :data="_address" doctype="Address" />
<ErrorMessage class="mt-2" :message="error" /> <ErrorMessage class="mt-2" :message="error" />
</div> </div>
</div> </div>
@ -54,7 +54,7 @@ import FieldLayout from '@/components/FieldLayout.vue'
import EditIcon from '@/components/Icons/EditIcon.vue' import EditIcon from '@/components/Icons/EditIcon.vue'
import { usersStore } from '@/stores/users' import { usersStore } from '@/stores/users'
import { capture } from '@/telemetry' import { capture } from '@/telemetry'
import { call, FeatherIcon, createResource, ErrorMessage } from 'frappe-ui' import { FeatherIcon, createResource, ErrorMessage } from 'frappe-ui'
import { ref, nextTick, watch, computed } from 'vue' import { ref, nextTick, watch, computed } from 'vue'
const props = defineProps({ const props = defineProps({

View File

@ -23,7 +23,11 @@
</div> </div>
</div> </div>
<div v-if="filteredSections.length"> <div v-if="filteredSections.length">
<FieldLayout :tabs="filteredSections" :data="_contact" /> <FieldLayout
:tabs="filteredSections"
:data="_contact"
doctype="Contact"
/>
</div> </div>
</div> </div>
<div class="px-4 pb-7 pt-4 sm:px-6"> <div class="px-4 pb-7 pt-4 sm:px-6">

View File

@ -38,6 +38,7 @@
v-if="filteredSections.length" v-if="filteredSections.length"
:tabs="filteredSections" :tabs="filteredSections"
:data="deal" :data="deal"
doctype="CRM Deal"
/> />
<ErrorMessage class="mt-4" v-if="error" :message="__(error)" /> <ErrorMessage class="mt-4" v-if="error" :message="__(error)" />
</div> </div>

View File

@ -23,7 +23,11 @@
</div> </div>
</div> </div>
<div v-if="filteredSections.length"> <div v-if="filteredSections.length">
<FieldLayout :tabs="filteredSections" :data="_organization" /> <FieldLayout
:tabs="filteredSections"
:data="_organization"
doctype="CRM Organization"
/>
</div> </div>
</div> </div>
<div class="px-4 pb-7 pt-4 sm:px-6"> <div class="px-4 pb-7 pt-4 sm:px-6">

View File

@ -12,7 +12,12 @@
/> />
</h2> </h2>
<div v-if="!data.get.loading" class="flex-1 overflow-y-auto"> <div v-if="!data.get.loading" class="flex-1 overflow-y-auto">
<FieldLayout v-if="data?.doc && tabs" :tabs="tabs" :data="data.doc" /> <FieldLayout
v-if="data?.doc && tabs"
:tabs="tabs"
:data="data.doc"
:doctype="doctype"
/>
<ErrorMessage class="mt-2" :message="error" /> <ErrorMessage class="mt-2" :message="error" />
</div> </div>
<div v-else class="flex flex-1 items-center justify-center"> <div v-else class="flex flex-1 items-center justify-center">

View File

@ -168,6 +168,17 @@
@change="(data) => emit('update', field.name, data)" @change="(data) => emit('update', field.name, data)"
/> />
</div> </div>
<FormControl
v-else-if="field.type === 'currency'"
class="form-control"
type="text"
:value="getFormattedCurrency(field.name, data)"
:placeholder="field.placeholder"
:debounce="500"
@change.stop="
emit('update', field.name, flt($event.target.value))
"
/>
<FormControl <FormControl
v-else v-else
class="form-control" class="form-control"
@ -203,8 +214,10 @@ import ArrowUpRightIcon from '@/components/Icons/ArrowUpRightIcon.vue'
import EditIcon from '@/components/Icons/EditIcon.vue' import EditIcon from '@/components/Icons/EditIcon.vue'
import Link from '@/components/Controls/Link.vue' import Link from '@/components/Controls/Link.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { getMeta } from '@/stores/meta'
import { usersStore } from '@/stores/users' import { usersStore } from '@/stores/users'
import { getFormat } from '@/utils' import { getFormat } from '@/utils'
import { flt } from '@/utils/numberFormat.js'
import { Tooltip, DateTimePicker, DatePicker } from 'frappe-ui' import { Tooltip, DateTimePicker, DatePicker } from 'frappe-ui'
import { computed } from 'vue' import { computed } from 'vue'
@ -212,12 +225,17 @@ const props = defineProps({
fields: { fields: {
type: Object, type: Object,
}, },
doctype: {
type: String,
default: 'CRM Lead',
},
isLastSection: { isLastSection: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}) })
const { getFormattedCurrency } = getMeta(props.doctype)
const { getUser } = usersStore() const { getUser } = usersStore()
const emit = defineEmits(['update']) const emit = defineEmits(['update'])

View File

@ -142,6 +142,7 @@
v-if="section.fields" v-if="section.fields"
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
doctype="Contact"
v-model="contact.data" v-model="contact.data"
@update="updateField" @update="updateField"
/> />

View File

@ -171,6 +171,7 @@
v-if="section.fields" v-if="section.fields"
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
doctype="CRM Deal"
v-model="deal.data" v-model="deal.data"
@update="updateField" @update="updateField"
/> />

View File

@ -145,6 +145,7 @@
<SidePanelLayout <SidePanelLayout
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
doctype="Contact"
v-model="contact.data" v-model="contact.data"
@update="updateField" @update="updateField"
/> />

View File

@ -102,6 +102,7 @@
v-if="section.fields" v-if="section.fields"
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
doctype="CRM Deal"
v-model="deal.data" v-model="deal.data"
@update="updateField" @update="updateField"
/> />

View File

@ -125,9 +125,10 @@
> >
<Section :label="section.label" :opened="section.opened"> <Section :label="section.label" :opened="section.opened">
<SidePanelLayout <SidePanelLayout
v-model="organization.doc"
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
v-model="organization.doc" doctype="CRM Organization"
@update="updateField" @update="updateField"
/> />
</Section> </Section>

View File

@ -125,9 +125,10 @@
</template> </template>
<SidePanelLayout <SidePanelLayout
v-if="section.fields" v-if="section.fields"
v-model="organization.doc"
:fields="section.fields" :fields="section.fields"
:isLastSection="i == fieldsLayout.data.length - 1" :isLastSection="i == fieldsLayout.data.length - 1"
v-model="organization.doc" doctype="CRM Organization"
@update="updateField" @update="updateField"
/> />
</Section> </Section>

View File

@ -59,7 +59,7 @@ export function cint(v, def) {
return v return v
} }
function flt(v, decimals, numberFormat, roundingMethod) { export function flt(v, decimals, numberFormat, roundingMethod) {
if (v == null || v == '') return 0 if (v == null || v == '') return 0
if (typeof v !== 'number') { if (typeof v !== 'number') {