163 lines
4.1 KiB
Vue
163 lines
4.1 KiB
Vue
<template>
|
|
<div
|
|
v-if="reply?.message"
|
|
class="flex items-center justify-around gap-2 px-10 pt-2"
|
|
>
|
|
<div
|
|
class="mb-1 ml-13 flex-1 cursor-pointer rounded border-0 border-l-4 border-green-500 bg-gray-100 p-2 text-base text-gray-600"
|
|
:class="reply.type == 'Incoming' ? 'border-green-500' : 'border-blue-400'"
|
|
>
|
|
<div
|
|
class="mb-1 text-sm font-bold"
|
|
:class="reply.type == 'Incoming' ? 'text-green-500' : 'text-blue-400'"
|
|
>
|
|
{{ reply.from_name || __('You') }}
|
|
</div>
|
|
<div class="max-h-12 overflow-hidden" v-html="reply.message" />
|
|
</div>
|
|
|
|
<Button variant="ghost" icon="x" @click="reply = {}" />
|
|
</div>
|
|
<div class="flex items-end gap-2 px-10 py-2.5">
|
|
<div class="flex h-8 items-center gap-2">
|
|
<FileUploader @success="(file) => uploadFile(file)">
|
|
<template v-slot="{ openFileSelector }">
|
|
<div class="flex items-center space-x-2">
|
|
<Dropdown :options="uploadOptions(openFileSelector)">
|
|
<FeatherIcon
|
|
name="plus"
|
|
class="size-4.5 cursor-pointer text-gray-600"
|
|
/>
|
|
</Dropdown>
|
|
</div>
|
|
</template>
|
|
</FileUploader>
|
|
<IconPicker
|
|
v-model="emoji"
|
|
v-slot="{ togglePopover }"
|
|
@update:modelValue="
|
|
() => {
|
|
content += emoji
|
|
$refs.textarea.$el.focus()
|
|
}
|
|
"
|
|
>
|
|
<SmileIcon
|
|
@click="togglePopover"
|
|
class="flex size-4.5 cursor-pointer rounded-sm text-xl leading-none text-gray-500"
|
|
/>
|
|
</IconPicker>
|
|
</div>
|
|
<Textarea
|
|
ref="textarea"
|
|
type="textarea"
|
|
class="min-h-8 w-full"
|
|
:rows="rows"
|
|
v-model="content"
|
|
:placeholder="placeholder"
|
|
@focus="rows = 6"
|
|
@blur="rows = 1"
|
|
@keydown.enter="(e) => sendTextMessage(e)"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import IconPicker from '@/components/IconPicker.vue'
|
|
import SmileIcon from '@/components/Icons/SmileIcon.vue'
|
|
import { createResource, Textarea, FileUploader, Dropdown } from 'frappe-ui'
|
|
import FeatherIcon from 'frappe-ui/src/components/FeatherIcon.vue'
|
|
import { ref, computed, nextTick, watch } from 'vue'
|
|
|
|
const props = defineProps({
|
|
doctype: String,
|
|
})
|
|
|
|
const doc = defineModel()
|
|
const whatsapp = defineModel('whatsapp')
|
|
const reply = defineModel('reply')
|
|
const rows = ref(1)
|
|
const textarea = ref(null)
|
|
const emoji = ref('')
|
|
|
|
const content = ref('')
|
|
const placeholder = ref(__('Type your message here...'))
|
|
const fileType = ref('')
|
|
|
|
function show() {
|
|
nextTick(() => textarea.value.$el.focus())
|
|
}
|
|
|
|
function uploadFile(file) {
|
|
whatsapp.value.attach = file.file_url
|
|
whatsapp.value.content_type = fileType.value
|
|
sendWhatsAppMessage()
|
|
}
|
|
|
|
function sendTextMessage(event) {
|
|
if (event.shiftKey) return
|
|
sendWhatsAppMessage()
|
|
textarea.value.$el.blur()
|
|
content.value = ''
|
|
}
|
|
|
|
async function sendWhatsAppMessage() {
|
|
let args = {
|
|
reference_doctype: props.doctype,
|
|
reference_name: doc.value.data.name,
|
|
message: content.value,
|
|
to: doc.value.data.mobile_no,
|
|
attach: whatsapp.value.attach || '',
|
|
reply_to: reply.value?.name || '',
|
|
content_type: whatsapp.value.content_type,
|
|
}
|
|
content.value = ''
|
|
fileType.value = ''
|
|
whatsapp.value.attach = ''
|
|
whatsapp.value.content_type = 'text'
|
|
reply.value = {}
|
|
createResource({
|
|
url: 'crm.api.whatsapp.create_whatsapp_message',
|
|
params: args,
|
|
auto: true,
|
|
})
|
|
}
|
|
|
|
function uploadOptions(openFileSelector) {
|
|
return [
|
|
{
|
|
label: __('Upload Document'),
|
|
icon: 'file',
|
|
onClick: () => {
|
|
fileType.value = 'document'
|
|
openFileSelector()
|
|
},
|
|
},
|
|
{
|
|
label: __('Upload Image'),
|
|
icon: 'image',
|
|
onClick: () => {
|
|
fileType.value = 'image'
|
|
openFileSelector('image/*')
|
|
},
|
|
},
|
|
{
|
|
label: __('Upload Video'),
|
|
icon: 'video',
|
|
onClick: () => {
|
|
fileType.value = 'video'
|
|
openFileSelector('video/*')
|
|
},
|
|
},
|
|
]
|
|
}
|
|
|
|
watch(reply, (value) => {
|
|
if (value?.message) {
|
|
show()
|
|
}
|
|
})
|
|
|
|
defineExpose({ show })
|
|
</script>
|