diff --git a/app/javascript/dashboard/components-next/NewConversation/components/WhatsappTemplateParser.vue b/app/javascript/dashboard/components-next/NewConversation/components/WhatsappTemplateParser.vue
index 9e747023d..0a2702b1c 100644
--- a/app/javascript/dashboard/components-next/NewConversation/components/WhatsappTemplateParser.vue
+++ b/app/javascript/dashboard/components-next/NewConversation/components/WhatsappTemplateParser.vue
@@ -53,23 +53,6 @@ const buttonComponents = computed(() => {
);
});
-const interactiveComponents = computed(() => {
- return templateComponents.value.filter(component =>
- ['LIST', 'PRODUCT', 'CATALOG'].includes(component.type)
- );
-});
-
-const isInteractiveTemplate = computed(() => {
- const hasInteractiveButtons = buttonComponents.value.some(component =>
- component.buttons?.some(button =>
- ['quick_reply', 'url', 'phone_number', 'catalog_browse'].includes(
- button.type
- )
- )
- );
- return hasInteractiveButtons || interactiveComponents.value.length > 0;
-});
-
const legacyParams = computed(() => {
const params = {};
Object.keys(processedParams.value).forEach(key => {
@@ -256,29 +239,6 @@ const generateVariables = () => {
}
});
- // Process interactive components (LIST, PRODUCT, CATALOG)
- interactiveComponents.value.forEach(component => {
- if (component.type === 'LIST') {
- allVariables.interactive = {
- type: 'list',
- button_text: 'Select Option',
- sections: component.sections || [],
- };
- } else if (component.type === 'PRODUCT') {
- allVariables.interactive = {
- type: 'product',
- catalog_id: component.catalog_id || '',
- product_id: component.product_id || '',
- };
- } else if (component.type === 'CATALOG') {
- allVariables.interactive = {
- type: 'catalog',
- catalog_id: component.catalog_id || '',
- title: component.title || 'Browse Products',
- };
- }
- });
-
processedParams.value = allVariables;
};
@@ -465,17 +425,18 @@ onMounted(() => {
- 🏢 Location Name
+ {{ t('WHATSAPP_TEMPLATES.PARSER.LOCATION_NAME') }}
{
@@ -621,101 +587,6 @@ onMounted(() => {
-
-
-
- {{
- t('WHATSAPP_TEMPLATES.PARSER.INTERACTIVE_PARAMETERS') ||
- 'Interactive Parameters'
- }}
-
-
-
-
-
-
-
-
-
-
-
- Button Text
-
-
-
- List sections are configured in the template and cannot be modified
- here.
-
-
-
-
diff --git a/app/javascript/dashboard/components/widgets/conversation/WhatsappTemplates/TemplatesPicker.vue b/app/javascript/dashboard/components/widgets/conversation/WhatsappTemplates/TemplatesPicker.vue
index fff118873..7a8470cbe 100644
--- a/app/javascript/dashboard/components/widgets/conversation/WhatsappTemplates/TemplatesPicker.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/WhatsappTemplates/TemplatesPicker.vue
@@ -35,8 +35,15 @@ export default {
return false;
}
- // Since we support all formats now, include all approved templates
- // This includes templates with media headers (IMAGE, VIDEO, DOCUMENT)
+ // Filter out interactive templates (LIST, PRODUCT, CATALOG)
+ const hasInteractiveComponents = template.components.some(component =>
+ ['LIST', 'PRODUCT', 'CATALOG'].includes(component.type)
+ );
+
+ if (hasInteractiveComponents) {
+ return false;
+ }
+
return true;
});
},
@@ -106,7 +113,7 @@ export default {
- {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.LANGUAGE') }} :
+ {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.LANGUAGE') }}:
{{ template.language }}
diff --git a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
index fc3de96d0..defa9f41b 100644
--- a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
@@ -25,7 +25,16 @@
"VARIABLE_PLACEHOLDER": "Enter {variable} value",
"GO_BACK_LABEL": "Go Back",
"SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "LOCATION_DETAILS": "Location Details",
+ "LATITUDE": "Latitude",
+ "LONGITUDE": "Longitude",
+ "LOCATION_NAME": "Location Name",
+ "FULL_ADDRESS": "Full Address",
+ "LATITUDE_RANGE": "Range: -90.0 to 90.0",
+ "LONGITUDE_RANGE": "Range: -180.0 to 180.0",
+ "LOCATION_TIP": "You can get coordinates by searching your location on Google Maps, right-clicking the pin, and copying the latitude/longitude values.",
+ "TIP_LABEL": "Tip:"
}
}
}
diff --git a/app/services/whatsapp/providers/whatsapp_cloud_service.rb b/app/services/whatsapp/providers/whatsapp_cloud_service.rb
index f35909f95..d1230e63f 100644
--- a/app/services/whatsapp/providers/whatsapp_cloud_service.rb
+++ b/app/services/whatsapp/providers/whatsapp_cloud_service.rb
@@ -12,15 +12,6 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi
end
def send_template(phone_number, template_info)
- # Check if this is an interactive template
- if template_info[:parameters].is_a?(Hash) && template_info[:parameters][:type] == 'interactive'
- send_interactive_template(phone_number, template_info)
- else
- send_regular_template(phone_number, template_info)
- end
- end
-
- def send_regular_template(phone_number, template_info)
template_body = template_body_parameters(template_info)
request_body = {
@@ -40,32 +31,6 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi
process_response(response)
end
- def send_interactive_template(phone_number, template_info)
- interactive_data = template_info[:parameters][:interactive_data]
-
- request_body = {
- messaging_product: 'whatsapp',
- recipient_type: 'individual',
- to: phone_number,
- type: 'interactive',
- interactive: {
- type: interactive_data[:type],
- body: {
- text: build_template_body_text(template_info)
- },
- action: interactive_data[:action]
- }
- }
-
- response = HTTParty.post(
- "#{phone_id_path}/messages",
- headers: api_headers,
- body: request_body.to_json
- )
-
- process_response(response)
- end
-
def sync_templates
# ensuring that channels with wrong provider config wouldn't keep trying to sync templates
whatsapp_channel.mark_message_templates_updated
@@ -221,13 +186,4 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi
process_response(response)
end
-
- private
-
- def build_template_body_text(template_info)
- # Build the template body text with parameter substitution
- # This is a simplified version - you might want to enhance this
- # to properly substitute template variables
- template_info[:name] || 'Interactive Template'
- end
end
diff --git a/app/services/whatsapp/template_processor_service.rb b/app/services/whatsapp/template_processor_service.rb
index ea2cf964e..52176a396 100644
--- a/app/services/whatsapp/template_processor_service.rb
+++ b/app/services/whatsapp/template_processor_service.rb
@@ -75,11 +75,8 @@ class Whatsapp::TemplateProcessorService
template = find_template
return if template.blank?
- # Check for interactive templates first
- if has_interactive_components?(template)
- process_interactive_template_params(template)
# Handle enhanced template parameters structure
- elsif template_params['processed_params'].is_a?(Hash) && template_params['processed_params'].key?('body')
+ if template_params['processed_params'].is_a?(Hash) && template_params['processed_params'].key?('body')
process_enhanced_template_params(template)
else
# Check if we have special header types that need processing
@@ -190,7 +187,7 @@ class Whatsapp::TemplateProcessorService
elsif key == 'location' && processed_params['header']['location_type'] == 'location'
location_param = build_location_parameter(value)
header_params << location_param if location_param
- elsif !%w[media_type location_type].include?(key)
+ elsif %w[media_type location_type].exclude?(key)
header_params << build_parameter(value)
end
end
@@ -448,7 +445,7 @@ class Whatsapp::TemplateProcessorService
when 'expiry'
# Expiry time in minutes
expiry_minutes = sanitized_value.to_i
- raise ArgumentError, 'Expiry minutes must be a positive number' unless expiry_minutes > 0
+ raise ArgumentError, 'Expiry minutes must be a positive number' unless expiry_minutes.positive?
{ type: 'text', text: expiry_minutes.to_s }
else
@@ -494,145 +491,6 @@ class Whatsapp::TemplateProcessorService
template['components'].find { |obj| obj['type'] == 'BODY' && obj.key?('text') }
end
- def has_interactive_components?(template)
- # Check if template has interactive buttons like quick replies, call-to-actions, etc.
- interactive_types = %w[quick_reply url phone_number copy_code list catalog_browse]
- template['components']&.any? do |component|
- (component['type'] == 'BUTTONS' && component['buttons']&.any? { |button| interactive_types.include?(button['type']) }) ||
- (component['type'] == 'LIST' && component['sections'].present?) ||
- (component['type'] == 'PRODUCT' && component['product_id'].present?) ||
- (component['type'] == 'CATALOG' && component['catalog_id'].present?)
- end
- end
-
- def process_interactive_template_params(template)
- components = []
-
- # Process body parameters
- if template_params['processed_params'].present?
- body_params = template_params['processed_params'].map { |_, value| { type: 'text', text: value } }
- components << { type: 'body', parameters: body_params } if body_params.present?
- end
-
- @template_params = {
- type: 'interactive',
- components: components,
- interactive_data: extract_interactive_data(template)
- }
- end
-
- def extract_interactive_data(template)
- # Check if this is a catalog browse template
- catalog_component = template['components'].find { |c| c['type'] == 'CATALOG' }
- return extract_catalog_data(catalog_component) if catalog_component&.dig('catalog_id')
-
- # Check if this is a product template
- product_component = template['components'].find { |c| c['type'] == 'PRODUCT' }
- return extract_product_data(product_component) if product_component&.dig('product_id')
-
- # Check if this is a list template
- list_component = template['components'].find { |c| c['type'] == 'LIST' }
- return extract_list_data(list_component) if list_component&.dig('sections')
-
- # Default to button template
- interactive_data = { type: 'button', action: { buttons: [] } }
-
- button_component = template['components'].find { |c| c['type'] == 'BUTTONS' }
- return interactive_data unless button_component&.dig('buttons')
-
- buttons = button_component['buttons'].map.with_index do |button, index|
- # Process dynamic button text if parameters are provided
- button_text = process_dynamic_button_text(button['text'] || '', index)
-
- case button['type']
- when 'quick_reply'
- {
- type: 'reply',
- reply: {
- id: "reply_#{index}",
- title: button_text || "Reply #{index + 1}"
- }
- }
- when 'url'
- {
- type: 'reply',
- reply: {
- id: "url_#{index}",
- title: button_text || 'Visit Link'
- }
- }
- when 'phone_number'
- {
- type: 'reply',
- reply: {
- id: "call_#{index}",
- title: button_text || 'Call Now'
- }
- }
- end
- end.compact.first(3) # WhatsApp allows max 3 reply buttons
-
- interactive_data[:action][:buttons] = buttons
- interactive_data
- end
-
- def extract_list_data(list_component)
- interactive_data = {
- type: 'list',
- action: {
- button: 'Select an Option',
- sections: []
- }
- }
-
- sections = list_component['sections'].map.with_index do |section, section_index|
- rows = section['rows']&.map&.with_index do |row, row_index|
- {
- id: "row_#{section_index}_#{row_index}",
- title: row['title'] || "Option #{row_index + 1}",
- description: row['description'] || nil
- }
- end&.first(10) || [] # WhatsApp allows max 10 rows per section
-
- {
- title: section['title'] || "Section #{section_index + 1}",
- rows: rows
- }
- end.first(10) # WhatsApp allows max 10 sections
-
- interactive_data[:action][:sections] = sections
- interactive_data
- end
-
- def extract_product_data(product_component)
- {
- type: 'product',
- action: {
- catalog_id: product_component['catalog_id'] || '',
- product_retailer_id: product_component['product_id']
- }
- }
- end
-
- def extract_catalog_data(catalog_component)
- {
- type: 'product_list',
- action: {
- catalog_id: catalog_component['catalog_id'],
- sections: [
- {
- title: catalog_component['title'] || 'Browse Products',
- product_items: catalog_component['products']&.map do |product|
- {
- product_retailer_id: product['id'] || product['product_id']
- }
- end || []
- }
- ]
- }
- }
- end
-
def process_dynamic_button_text(button_text, button_index)
return button_text unless button_text.include?('{{')
@@ -651,7 +509,7 @@ class Whatsapp::TemplateProcessorService
button_text
end
- def has_rich_formatting?(text)
+ def rich_formatting?(text)
# Check if text contains WhatsApp rich formatting markers
text.match?(/\*[^*]+\*/) || # Bold: *text*
text.match?(/_[^_]+_/) || # Italic: _text_