chore: Fix whats app template
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
+2
-6
@@ -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..."
|
||||
|
||||
+12
-6
@@ -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" />
|
||||
|
||||
+56
-28
@@ -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')"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user