chore: Fix whats app template

This commit is contained in:
iamsivin
2024-11-15 14:30:46 +05:30
parent 9ea992fe45
commit 7790b88725
4 changed files with 71 additions and 41 deletions
@@ -396,9 +396,9 @@ watch(
/>
<MessageEditor
v-if="!isWhatsappInbox"
v-model="state.message"
:is-email-or-web-widget-inbox="isEmailOrWebWidgetInbox"
:is-whatsapp-inbox="isWhatsappInbox"
/>
</div>
@@ -11,17 +11,13 @@ defineProps({
type: Boolean,
required: true,
},
isWhatsappInbox: {
type: Boolean,
required: true,
},
});
const emit = defineEmits(['update:modelValue']);
</script>
<template>
<div v-if="isEmailOrWebWidgetInbox" class="flex-1 h-full">
<div v-if="isEmailOrWebWidgetInbox" class="flex-1 h-full min-h-[200px]">
<Editor
:model-value="modelValue"
placeholder="Write your message here..."
@@ -30,7 +26,7 @@ const emit = defineEmits(['update:modelValue']);
@update:model-value="emit('update:modelValue', $event)"
/>
</div>
<div v-else-if="!isWhatsappInbox" class="flex-1 h-full">
<div v-else class="flex-1 h-full min-h-[200px]">
<TextArea
:model-value="modelValue"
placeholder="Write your message here..."
@@ -6,8 +6,8 @@ import WhatsappTemplateParser from './WhatsappTemplateParser.vue';
const props = defineProps({
messageTemplates: {
type: Object,
default: () => {},
type: Array,
default: () => [],
},
});
@@ -22,10 +22,16 @@ const selectedTemplate = ref(null);
const showTemplatesMenu = ref(false);
const whatsAppTemplateMessages = computed(() => {
return props.messageTemplates
.filter(template => template.status.toLowerCase() === 'approved')
// Add null check and ensure it's an array
const templates = Array.isArray(props.messageTemplates)
? props.messageTemplates
: [];
// TODO: Remove the last filter when we support all formats
return templates
.filter(template => template?.status?.toLowerCase() === 'approved')
.filter(template => {
return template.components.every(component => {
return template?.components?.every(component => {
return !formatsToRemove.includes(component.format);
});
});
@@ -75,7 +81,7 @@ const handleSendMessage = template => {
/>
<div
v-if="showTemplatesMenu"
class="absolute top-full mt-1.5 left-0 flex flex-col gap-2 p-4 items-center w-[350px] h-auto bg-n-solid-2 border border-n-strong shadow-sm rounded-lg"
class="absolute top-full mt-1.5 max-h-96 overflow-y-auto left-0 flex flex-col gap-2 p-4 items-center w-[350px] h-auto bg-n-solid-2 border border-n-strong shadow-sm rounded-lg"
>
<div class="relative w-full">
<span class="absolute i-lucide-search size-3.5 top-2 left-3" />
@@ -17,21 +17,16 @@ const emit = defineEmits(['sendMessage', 'back']);
const processedParams = ref({});
const templateName = computed(() => {
return props.template?.name || '';
});
const templateString = computed(() => {
return props.template?.components?.find(
component => component.type === 'BODY'
).text;
});
const allKeysRequired = value => {
const keys = Object.keys(value);
return keys.every(key => value[key]);
};
const variables = computed(() => {
return templateString.value.match(/{{([^}]+)}}/g);
});
const processVariable = str => {
return str.replace(/{{|}}/g, '');
};
@@ -43,15 +38,35 @@ const processedString = computed(() => {
});
});
const v$ = useVuelidate(
{
processedParams: {
requiredIfKeysPresent: requiredIf(variables),
allKeysRequired,
},
},
{ processedParams }
);
const processedStringWithVariableHighlight = computed(() => {
const variables = templateString.value.match(/{{([^}]+)}}/g) || [];
return variables.reduce((result, variable) => {
const variableKey = processVariable(variable);
const value = processedParams.value[variableKey] || variable;
return result.replace(
variable,
`<span class="break-all text-n-slate-12">${value}</span>`
);
}, templateString.value);
});
const rules = computed(() => {
const paramRules = {};
Object.keys(processedParams.value).forEach(key => {
paramRules[key] = { required: requiredIf(true) };
});
return {
processedParams: paramRules,
};
});
const v$ = useVuelidate(rules, { processedParams });
const getFieldErrorType = key => {
if (!v$.value.processedParams[key]?.$error) return 'info';
return 'error';
};
const generateVariables = () => {
const matchedVariables = templateString.value.match(/{{([^}]+)}}/g);
@@ -64,9 +79,9 @@ const generateVariables = () => {
}, {});
};
const sendMessage = () => {
v$.value.$touch();
if (v$.value.$invalid) return;
const sendMessage = async () => {
const isValid = await v$.value.$validate();
if (!isValid) return;
const payload = {
message: processedString.value,
@@ -88,15 +103,18 @@ onMounted(() => {
<template>
<div
class="absolute top-full mt-1.5 left-0 flex flex-col gap-4 px-4 pt-6 pb-5 items-start w-[460px] h-auto bg-n-solid-2 border border-n-strong shadow-sm rounded-lg"
class="absolute top-full mt-1.5 max-h-[500px] overflow-y-auto left-0 flex flex-col gap-4 px-4 pt-6 pb-5 items-start w-[460px] h-auto bg-n-solid-2 border border-n-strong shadow-sm rounded-lg"
>
<span class="text-sm text-n-slate-12">
{{ `WhatsApp template: ${template.name}` }}
{{ `WhatsApp template: ${templateName}` }}
</span>
<p class="mb-0 text-sm text-n-slate-11">{{ processedString }}</p>
<p
class="mb-0 text-sm text-n-slate-11"
v-html="processedStringWithVariableHighlight"
/>
<span
v-if="processedParams.length"
v-if="Object.keys(processedParams).length"
class="text-sm font-medium text-n-slate-12"
>
{{ 'Variables' }}
@@ -105,16 +123,26 @@ onMounted(() => {
<div
v-for="(variable, key) in processedParams"
:key="key"
class="flex flex-col w-full gap-4"
class="flex items-center w-full gap-2"
>
<span class="w-8 h-8 text-sm text-left text-n-slate-12">{{ key }}</span>
<Input v-model="processedParams[key]" custom-input-class="!h-8" />
<span
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
>
{{ key }}
</span>
<Input
v-model="processedParams[key]"
custom-input-class="!h-8 w-full !bg-transparent"
class="w-full"
:message-type="getFieldErrorType(key)"
/>
</div>
<div class="flex items-end justify-between w-full gap-3 h-14">
<Button
label="Go back"
color="slate"
variant="faded"
class="w-full font-medium"
@click="emit('back')"
/>